diff --git a/Zend/tests/autoload/class/autoload_call_basic.phpt b/Zend/tests/autoload/class/autoload_call_basic.phpt new file mode 100644 index 0000000000000..eae6361fe89c1 --- /dev/null +++ b/Zend/tests/autoload/class/autoload_call_basic.phpt @@ -0,0 +1,17 @@ +--TEST-- +Basic autoload_call_class() function +--CREDITS-- +Jean-Marc Fontaine +# Alter Way Contribution Day 2011 +--FILE-- + +--EXPECT-- +bool(true) diff --git a/Zend/tests/autoload/class/autoload_call_invalid_name.phpt b/Zend/tests/autoload/class/autoload_call_invalid_name.phpt new file mode 100644 index 0000000000000..95ffae3569b20 --- /dev/null +++ b/Zend/tests/autoload/class/autoload_call_invalid_name.phpt @@ -0,0 +1,36 @@ +--TEST-- +Test autoload_call_class() with invalid symbol name +--FILE-- +getMessage(); +} +try { + autoload_call_class('"'); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(); +} +try { + autoload_call_class(''); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(); +} +try { + autoload_call_class("al\no"); +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(); +} +?> +--EXPECT-- +string(6) "12ayhs" +string(1) """ +string(0) "" +string(4) "al +o" diff --git a/ext/spl/tests/spl_autoload_called_scope.phpt b/Zend/tests/autoload/class/autoload_called_scope.phpt similarity index 72% rename from ext/spl/tests/spl_autoload_called_scope.phpt rename to Zend/tests/autoload/class/autoload_called_scope.phpt index 23f2e84d952b6..d19fc3d9c91d2 100644 --- a/ext/spl/tests/spl_autoload_called_scope.phpt +++ b/Zend/tests/autoload/class/autoload_called_scope.phpt @@ -1,11 +1,11 @@ --TEST-- -SPL autoloader should not do anything magic with called scope +Autoloader should not do anything magic with called scope --FILE-- getMessage(), \PHP_EOL; +} +$name = '"'; +try { + new $name; +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +$name = ''; +try { + new $name; +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +$name = "al\no"; +try { + new $name; +} catch (\Throwable $e) { + echo $e::class, ': ', $e->getMessage(), \PHP_EOL; +} +?> +--EXPECT-- +string(6) "12ayhs" +Error: Class "12ayhs" not found +Error: Class """ not found +Error: Class "" not found +Error: Class "al +o" not found diff --git a/Zend/tests/autoload/class/autoloader_with_closures_and_invocables.phpt b/Zend/tests/autoload/class/autoloader_with_closures_and_invocables.phpt new file mode 100644 index 0000000000000..08a9fe8d3b881 --- /dev/null +++ b/Zend/tests/autoload/class/autoloader_with_closures_and_invocables.phpt @@ -0,0 +1,68 @@ +--TEST-- +Autoloading with closures and invocables +--FILE-- +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'); + +autoload_register_class($closure); +autoload_register_class($al1); +autoload_register_class($al2); + +var_dump(autoload_list_class()); + +$x = new TestX; + +autoload_unregister_class($closure); +autoload_unregister_class($al1); + +$y = new TestY; + +?> +--EXPECTF-- +array(3) { + [0]=> + object(Closure)#1 (4) { + ["name"]=> + string(%d) "{closure:%s:%d}" + ["file"]=> + string(%d) "%s" + ["line"]=> + int(2) + ["parameter"]=> + array(1) { + ["$name"]=> + string(10) "" + } + } + [1]=> + object(Autoloader)#2 (1) { + ["dir":"Autoloader":private]=> + string(2) "d1" + } + [2]=> + object(WorkingAutoloader)#3 (0) { + } +} +autoload(TestX) +Autoloader('d1') called with TestX +WorkingAutoloader() called with TestX +WorkingAutoloader() called with TestY diff --git a/Zend/tests/autoload/bug42798.phpt b/Zend/tests/autoload/class/bug42798.phpt similarity index 55% rename from Zend/tests/autoload/bug42798.phpt rename to Zend/tests/autoload/class/bug42798.phpt index 5f19fe3080255..23a38b7cbc730 100644 --- a/Zend/tests/autoload/bug42798.phpt +++ b/Zend/tests/autoload/class/bug42798.phpt @@ -1,8 +1,8 @@ --TEST-- -Bug #42798 (_autoload() not triggered for classes used in method signature) +Bug #42798 (Autoloading not triggered for classes used in method signature) --FILE-- --EXPECTF-- diff --git a/Zend/tests/autoload/class/bug71204.phpt b/Zend/tests/autoload/class/bug71204.phpt new file mode 100644 index 0000000000000..bb75036ed9c05 --- /dev/null +++ b/Zend/tests/autoload/class/bug71204.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #71204 (segfault if clean autoloaders while autoloading) +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Class "A" not found in %s:%d +Stack trace: +#0 {main} + thrown in %sbug71204.php on line %d diff --git a/ext/spl/tests/bug73896.phpt b/Zend/tests/autoload/class/bug73896.phpt similarity index 70% rename from ext/spl/tests/bug73896.phpt rename to Zend/tests/autoload/class/bug73896.phpt index 657f30c50dbec..3e32bac243e47 100644 --- a/ext/spl/tests/bug73896.phpt +++ b/Zend/tests/autoload/class/bug73896.phpt @@ -1,16 +1,16 @@ --TEST-- -Bug #73896 (spl_autoload() crashes when calls magic _call()) +Bug #73896 (autoload_register_class() crashes when calls magic __call()) --FILE-- var = 2; -spl_autoload_register(array($a, 'autoload')); +autoload_register_class(array($a, 'autoload')); unset($a); var_dump(class_exists("C", true)); diff --git a/ext/spl/tests/bug74372.phpt b/Zend/tests/autoload/class/emit-parse-error-in-autoloader.phpt similarity index 51% rename from ext/spl/tests/bug74372.phpt rename to Zend/tests/autoload/class/emit-parse-error-in-autoloader.phpt index c2506009a5846..a5c70c8faf1ac 100644 --- a/ext/spl/tests/bug74372.phpt +++ b/Zend/tests/autoload/class/emit-parse-error-in-autoloader.phpt @@ -1,12 +1,12 @@ --TEST-- -Bug #74372: autoloading file with syntax error uses next autoloader, may hide parse error +Parse errors should be thrown if occuring from an autoloader --FILE-- getMessage() . "\n"; } diff --git a/ext/spl/tests/spl_autoload_008.phpt b/Zend/tests/autoload/class/exceptions_during_autoloading002.phpt similarity index 77% rename from ext/spl/tests/spl_autoload_008.phpt rename to Zend/tests/autoload/class/exceptions_during_autoloading002.phpt index 738c691ddfe9f..e1baf602e96ff 100644 --- a/ext/spl/tests/spl_autoload_008.phpt +++ b/Zend/tests/autoload/class/exceptions_during_autoloading002.phpt @@ -1,7 +1,5 @@ --TEST-- -SPL: spl_autoload() with exceptions ---INI-- -include_path=. +Exceptions during autoloading --FILE-- $func) var_dump($func); try { - spl_autoload_register($func); + autoload_register_class($func); } catch (TypeError $e) { echo get_class($e) . ': ' . $e->getMessage() . \PHP_EOL; - var_dump(count(spl_autoload_functions())); + var_dump(count(autoload_list_class())); continue; } - if (count(spl_autoload_functions())) { + if (count(autoload_list_class())) { echo "registered\n"; try { @@ -61,8 +59,8 @@ foreach($funcs as $idx => $func) } } - spl_autoload_unregister($func); - var_dump(count(spl_autoload_functions())); + autoload_unregister_class($func); + var_dump(count(autoload_list_class())); } ?> @@ -81,7 +79,7 @@ Exception: Bla int(0) ====2==== string(22) "MyAutoLoader::dynaLoad" -TypeError: spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, non-static method MyAutoLoader::dynaLoad() cannot be called statically +TypeError: autoload_register_class(): Argument #1 ($callback) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically int(0) ====3==== array(2) { @@ -101,7 +99,7 @@ array(2) { [1]=> string(8) "dynaLoad" } -TypeError: spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, non-static method MyAutoLoader::dynaLoad() cannot be called statically +TypeError: autoload_register_class(): Argument #1 ($callback) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically int(0) ====5==== array(2) { diff --git a/ext/spl/tests/spl_autoload_012.phpt b/Zend/tests/autoload/class/exceptions_during_autoloading003.phpt similarity index 66% rename from ext/spl/tests/spl_autoload_012.phpt rename to Zend/tests/autoload/class/exceptions_during_autoloading003.phpt index 218d3e800ff23..45ef5599f7cce 100644 --- a/ext/spl/tests/spl_autoload_012.phpt +++ b/Zend/tests/autoload/class/exceptions_during_autoloading003.phpt @@ -1,22 +1,20 @@ --TEST-- -SPL: spl_autoload() capturing multiple Exceptions in __autoload +Capturing multiple Exceptions during autoloading --FILE-- $func) if ($idx) echo "\n"; try { var_dump($func); - spl_autoload_register($func); + autoload_register_class($func); echo "ok\n"; } catch(\TypeError $e) { echo $e->getMessage() . \PHP_EOL; @@ -52,16 +52,16 @@ foreach($funcs as $idx => $func) ?> --EXPECTF-- string(22) "MyAutoLoader::notExist" -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, class MyAutoLoader does not have a method "notExist" +autoload_register_class(): Argument #1 ($callback) must be a valid callback, class MyAutoLoader does not have a method "notExist" string(22) "MyAutoLoader::noAccess" -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, cannot access protected method MyAutoLoader::noAccess() +autoload_register_class(): Argument #1 ($callback) must be a valid callback, cannot access protected method MyAutoLoader::noAccess() string(22) "MyAutoLoader::autoLoad" ok string(22) "MyAutoLoader::dynaLoad" -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, non-static method MyAutoLoader::dynaLoad() cannot be called statically +autoload_register_class(): Argument #1 ($callback) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically array(2) { [0]=> @@ -69,7 +69,7 @@ array(2) { [1]=> string(8) "notExist" } -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, class MyAutoLoader does not have a method "notExist" +autoload_register_class(): Argument #1 ($callback) must be a valid callback, class MyAutoLoader does not have a method "notExist" array(2) { [0]=> @@ -77,7 +77,7 @@ array(2) { [1]=> string(8) "noAccess" } -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, cannot access protected method MyAutoLoader::noAccess() +autoload_register_class(): Argument #1 ($callback) must be a valid callback, cannot access protected method MyAutoLoader::noAccess() array(2) { [0]=> @@ -93,7 +93,7 @@ array(2) { [1]=> string(8) "dynaLoad" } -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, non-static method MyAutoLoader::dynaLoad() cannot be called statically +autoload_register_class(): Argument #1 ($callback) must be a valid callback, non-static method MyAutoLoader::dynaLoad() cannot be called statically array(2) { [0]=> @@ -102,7 +102,7 @@ array(2) { [1]=> string(8) "notExist" } -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, class MyAutoLoader does not have a method "notExist" +autoload_register_class(): Argument #1 ($callback) must be a valid callback, class MyAutoLoader does not have a method "notExist" array(2) { [0]=> @@ -111,7 +111,7 @@ array(2) { [1]=> string(8) "noAccess" } -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, cannot access protected method MyAutoLoader::noAccess() +autoload_register_class(): Argument #1 ($callback) must be a valid callback, cannot access protected method MyAutoLoader::noAccess() array(2) { [0]=> diff --git a/Zend/tests/autoload/class/methods.phpt b/Zend/tests/autoload/class/methods.phpt new file mode 100644 index 0000000000000..f2f37f70ed23a --- /dev/null +++ b/Zend/tests/autoload/class/methods.phpt @@ -0,0 +1,43 @@ +--TEST-- +Autoloader is a method +--FILE-- +getMessage() . \PHP_EOL; +} + +// and + +$myAutoLoader = new MyAutoLoader(); + +autoload_register_class(array($myAutoLoader, 'autoLoad')); +autoload_register_class(array($myAutoLoader, 'autoThrow')); + +try { + var_dump(class_exists("TestClass", true)); +} catch(Exception $e) { + echo 'Exception: ' . $e->getMessage() . "\n"; +} + +?> +--EXPECT-- +autoload_register_class(): Argument #1 ($callback) must be a valid callback, non-static method MyAutoLoader::autoLoad() cannot be called statically +MyAutoLoader::autoLoad(TestClass) +MyAutoLoader::autoThrow(TestClass) +Exception: Unavailable diff --git a/Zend/tests/autoload/class/prepending.phpt b/Zend/tests/autoload/class/prepending.phpt new file mode 100644 index 0000000000000..6b048732c6838 --- /dev/null +++ b/Zend/tests/autoload/class/prepending.phpt @@ -0,0 +1,34 @@ +--TEST-- +Prepending autoloaders +--FILE-- + $name\n"; +} +function autoloadB($name) { + echo "B -> $name\n"; +} +function autoloadC($name) { + echo "C -> $name\n"; + class C{} +} + +autoload_register_class('autoloadA'); +autoload_register_class('autoloadB', true); +autoload_register_class('autoloadC'); +var_dump(autoload_list_class()); + +new C; +?> +--EXPECT-- +array(3) { + [0]=> + string(9) "autoloadB" + [1]=> + string(9) "autoloadA" + [2]=> + string(9) "autoloadC" +} +B -> C +A -> C +C -> C diff --git a/Zend/tests/autoload/class/register_class.phpt b/Zend/tests/autoload/class/register_class.phpt new file mode 100644 index 0000000000000..d44fcbcda3b7b --- /dev/null +++ b/Zend/tests/autoload/class/register_class.phpt @@ -0,0 +1,59 @@ +--TEST-- +Test autoload_register_class(): basic function behavior 001 +--FILE-- +getMessage(), \PHP_EOL; +} +*/ +echo "===EMPTY===\n"; + +function TestFunc1($classname) { + echo __METHOD__ . "($classname)\n"; +} + +function TestFunc2($classname) { + echo __METHOD__ . "($classname)\n"; +} + +echo "===REGISTER===\n"; + +autoload_register_class("TestFunc1"); +autoload_register_class("TestFunc2"); +autoload_register_class("TestFunc2"); // 2nd call ignored + +var_dump(class_exists("TestClass", true)); + +echo "===LOAD===\n"; + +autoload_register_class("spl_autoload"); +var_dump(class_exists("TestClass", true)); + +echo "===NOFUNCTION===\n"; + +try { + autoload_register_class("unavailable_autoload_function"); +} catch(\TypeError $e) { + echo $e->getMessage() . \PHP_EOL; +} + +?> +--EXPECT-- +===EMPTY=== +===REGISTER=== +TestFunc1(TestClass) +TestFunc2(TestClass) +bool(false) +===LOAD=== +TestFunc1(TestClass) +TestFunc2(TestClass) +bool(false) +===NOFUNCTION=== +autoload_register_class(): Argument #1 ($callback) must be a valid callback, function "unavailable_autoload_function" not found or invalid function name diff --git a/Zend/tests/autoload/class/same_class_different_instances.phpt b/Zend/tests/autoload/class/same_class_different_instances.phpt new file mode 100644 index 0000000000000..a995b26532f3c --- /dev/null +++ b/Zend/tests/autoload/class/same_class_different_instances.phpt @@ -0,0 +1,47 @@ +--TEST-- +Registering two different instance of a class as an autoloader should work +--FILE-- +directory_to_use, "\n"; + } +} + +$autoloader1 = new MyAutoloader('dir1'); +autoload_register_class(array($autoloader1, 'autoload')); + +$autoloader2 = new MyAutoloader('dir2'); +autoload_register_class(array($autoloader2, 'autoload')); + +var_dump(autoload_list_class()); +var_dump(class_exists('NonExisting')); + +?> +--EXPECT-- +array(2) { + [0]=> + array(2) { + [0]=> + object(MyAutoloader)#1 (1) { + ["directory_to_use":"MyAutoloader":private]=> + string(4) "dir1" + } + [1]=> + string(8) "autoload" + } + [1]=> + array(2) { + [0]=> + object(MyAutoloader)#2 (1) { + ["directory_to_use":"MyAutoloader":private]=> + string(4) "dir2" + } + [1]=> + string(8) "autoload" + } +} +dir1 +dir2 +bool(false) diff --git a/ext/spl/tests/spl_autoload_006.phpt b/Zend/tests/autoload/class/static_methods.phpt similarity index 52% rename from ext/spl/tests/spl_autoload_006.phpt rename to Zend/tests/autoload/class/static_methods.phpt index 7db2b462ca367..c6903ad337b61 100644 --- a/ext/spl/tests/spl_autoload_006.phpt +++ b/Zend/tests/autoload/class/static_methods.phpt @@ -1,20 +1,17 @@ --TEST-- -SPL: spl_autoload() with static methods ---INI-- -include_path=. +Autoloader is a static method --FILE-- getMessage() . \PHP_EOL; +} + +?> +--EXPECT-- +autoload_register_class(): Argument #1 ($callback) must not be the autoload_call_class() function diff --git a/Zend/tests/autoload/class/trampoline_autoloader.phpt b/Zend/tests/autoload/class/trampoline_autoloader.phpt new file mode 100644 index 0000000000000..506c5333f0484 --- /dev/null +++ b/Zend/tests/autoload/class/trampoline_autoloader.phpt @@ -0,0 +1,56 @@ +--TEST-- +Test autoload_unregister_class(): behavior with a trampoline +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + array(2) { + [0]=> + object(TrampolineTest)#1 (0) { + } + [1]=> + string(11) "trampoline1" + } + [1]=> + array(2) { + [0]=> + object(TrampolineTest)#1 (0) { + } + [1]=> + string(11) "trampoline2" + } +} +Trampoline for trampoline1 +Trampoline for trampoline2 +bool(false) +Unregister trampoline: +bool(true) +bool(false) +bool(true) +bool(false) diff --git a/Zend/tests/autoload/class/trampoline_unregister_autoloader_from_list.phpt b/Zend/tests/autoload/class/trampoline_unregister_autoloader_from_list.phpt new file mode 100644 index 0000000000000..6ef40a42a19d4 --- /dev/null +++ b/Zend/tests/autoload/class/trampoline_unregister_autoloader_from_list.phpt @@ -0,0 +1,46 @@ +--TEST-- +Unregister all class autoloaders by traversing the registered list: behavior with a trampoline +--FILE-- + +--EXPECT-- +array(2) { + [0]=> + array(2) { + [0]=> + object(TrampolineTest)#1 (0) { + } + [1]=> + string(11) "trampoline1" + } + [1]=> + array(2) { + [0]=> + object(TrampolineTest)#1 (0) { + } + [1]=> + string(11) "trampoline2" + } +} +array(0) { +} diff --git a/ext/spl/tests/bug71202.phpt b/Zend/tests/autoload/class/un-register_take_effect_immediately.phpt similarity index 68% rename from ext/spl/tests/bug71202.phpt rename to Zend/tests/autoload/class/un-register_take_effect_immediately.phpt index 84c9b609445f1..2b66aaca247f0 100644 --- a/ext/spl/tests/bug71202.phpt +++ b/Zend/tests/autoload/class/un-register_take_effect_immediately.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug #71202 (Autoload function registered by another not activated immediately) +(Un)Registering autoloaders must take effect immidiately --FILE-- +--EXPECT-- +TestFunc1(TestClass) +TestFunc2(TestClass) +bool(false) +bool(true) +bool(false) +TestFunc2(TestClass) +bool(false) diff --git a/Zend/tests/autoload/class/unregister_autoloader_from_list.phpt b/Zend/tests/autoload/class/unregister_autoloader_from_list.phpt new file mode 100644 index 0000000000000..1072abfe6c5bb --- /dev/null +++ b/Zend/tests/autoload/class/unregister_autoloader_from_list.phpt @@ -0,0 +1,22 @@ +--TEST-- +Unregister all autoloaders by traversing the registered list +--FILE-- + +--EXPECT-- +array(0) { +} diff --git a/Zend/tests/autoload/class_maps/basic_test.phpt b/Zend/tests/autoload/class_maps/basic_test.phpt new file mode 100644 index 0000000000000..ebc718b2d4122 --- /dev/null +++ b/Zend/tests/autoload/class_maps/basic_test.phpt @@ -0,0 +1,23 @@ +--TEST-- +Check that assigned class map works +--FILE-- + $pathTo . "Foo.inc", + 'Bar' => $pathTo . "Bar.inc", +]; + +autoload_register_class_map($classes); + +$f = new Foo(); +var_dump($f); +$b = new Bar(); +var_dump($b); + +?> +--EXPECT-- +object(Foo)#1 (0) { +} +object(Bar)#2 (0) { +} diff --git a/Zend/tests/autoload/class_maps/check_map_is_valid.phpt b/Zend/tests/autoload/class_maps/check_map_is_valid.phpt new file mode 100644 index 0000000000000..d31e049bcecd4 --- /dev/null +++ b/Zend/tests/autoload/class_maps/check_map_is_valid.phpt @@ -0,0 +1,48 @@ +--TEST-- +Check that assigned class map works +--FILE-- +getMessage(), PHP_EOL; + } +} + +$pathTo = __DIR__ . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR; +$map = [ + 'Foo' => $pathTo . "Foo.inc", + 'not a symbol name' => $pathTo . "Bar.inc", +]; +test_map($map); + +$map = [ + 'Foo' => $pathTo . "Foo.inc", + 0 => $pathTo . "Bar.inc", +]; +test_map($map); + +$map = [ + 'Foo' => 0, +]; +test_map($map); + +$map = [ + 'Foo' => "", +]; +test_map($map); + +$map = [ + 'Foo' => "Path\0hasNull", +]; +test_map($map); + +?> +--EXPECT-- +ValueError: autoload_register_class_map(): Argument #1 ($classes) key "not a symbol name" is not a valid class name +ValueError: autoload_register_class_map(): Argument #1 ($classes) must only have string keys +TypeError: autoload_register_class_map(): Argument #1 ($classes) path for class "Foo" must be of type string +ValueError: autoload_register_class_map(): Argument #1 ($classes) path for class "Foo" must not be empty +ValueError: autoload_register_class_map(): Argument #1 ($classes) path for class "Foo" must not contain null bytes diff --git a/Zend/tests/autoload/class_maps/classes/Bar.inc b/Zend/tests/autoload/class_maps/classes/Bar.inc new file mode 100644 index 0000000000000..bd6b6f454a463 --- /dev/null +++ b/Zend/tests/autoload/class_maps/classes/Bar.inc @@ -0,0 +1,5 @@ + | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_API.h" +#include "zend_autoload.h" +#include "zend_hash.h" +#include "zend_types.h" +#include "zend_exceptions.h" +#include "zend_string.h" + +ZEND_TLS HashTable *autoloader_class_autoload_functions; +ZEND_TLS HashTable *autoloader_class_map; + +#define HT_MOVE_TAIL_TO_HEAD(ht) \ + do { \ + Bucket tmp = (ht)->arData[(ht)->nNumUsed-1]; \ + memmove((ht)->arData + 1, (ht)->arData, \ + sizeof(Bucket) * ((ht)->nNumUsed - 1)); \ + (ht)->arData[0] = tmp; \ + if (!((ht)->u.flags & HASH_FLAG_PACKED)) { \ + zend_hash_rehash(ht); \ + } else { \ + zend_autoload_reindex(ht); \ + } \ + } while (false) + +static void zend_autoload_reindex(HashTable *ht) +{ + ZEND_ASSERT(ht->u.flags & HASH_FLAG_PACKED); + for (size_t i = 0; i < ht->nNumUsed; i++) { + ht->arData[i].h = i; + } +} + +ZEND_API void zend_autoload_callback_zval_destroy(zval *element) +{ + zend_fcall_info_cache *fcc = Z_PTR_P(element); + zend_fcc_dtor(fcc); + efree(fcc); +} + +static Bucket *autoload_find_registered_function(const HashTable *autoloader_table, const zend_fcall_info_cache *function_entry) +{ + zend_fcall_info_cache *current_function_entry; + ZEND_HASH_MAP_FOREACH_PTR(autoloader_table, current_function_entry) { + if (zend_fcc_equals(current_function_entry, function_entry)) { + return _p; + } + } ZEND_HASH_FOREACH_END(); + return NULL; +} + +ZEND_API zend_class_entry *zend_perform_class_autoload(zend_string *class_name, zend_string *lc_name) +{ + if (!autoloader_class_autoload_functions) { + return NULL; + } + + zval zname; + ZVAL_STR(&zname, class_name); + + const HashTable *class_autoload_functions = autoloader_class_autoload_functions; + + /* Cannot use ZEND_HASH_MAP_FOREACH_PTR here as autoloaders may be + * added/removed during autoloading. */ + HashPosition pos; + zend_hash_internal_pointer_reset_ex(class_autoload_functions, &pos); + while (true) { + zend_fcall_info_cache *func_info = zend_hash_get_current_data_ptr_ex(class_autoload_functions, &pos); + if (!func_info) { + break; + } + zend_call_known_fcc(func_info, /* retval */ NULL, /* param_count */ 1, /* params */ &zname, /* named_params */ NULL); + + if (EG(exception)) { + return NULL; + } + if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) { + return (zend_class_entry*)ZSTR_GET_CE_CACHE(class_name); + } + + zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name); + if (ce) { + return ce; + } + + zend_hash_move_forward_ex(class_autoload_functions, &pos); + } + return NULL; +} + +#define ZEND_FAKE_OP_ARRAY ((zend_op_array*)(intptr_t)-1) + +static zend_never_inline zend_op_array* zend_autoload_execute_file(zend_string *file_path) +{ + zend_op_array *new_op_array = NULL; + zend_file_handle file_handle; + + ZEND_ASSERT(!zend_str_has_nul_byte(file_path)); + + zend_string *resolved_path = zend_resolve_path(file_path); + if (EXPECTED(resolved_path)) { + /* If file has already been required once */ + if (zend_hash_exists(&EG(included_files), resolved_path)) { + zend_string_release_ex(resolved_path, false); + return ZEND_FAKE_OP_ARRAY; + } + } else if (UNEXPECTED(EG(exception))) { + return NULL; + } else { + resolved_path = zend_string_copy(file_path); + } + + zend_stream_init_filename_ex(&file_handle, resolved_path); + if (SUCCESS == zend_stream_open(&file_handle)) { + if (!file_handle.opened_path) { + file_handle.opened_path = zend_string_copy(resolved_path); + } + + if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path)) { + new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE); + } else { + new_op_array = ZEND_FAKE_OP_ARRAY; + } + } else if (!EG(exception)) { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_path); + } + zend_destroy_file_handle(&file_handle); + zend_string_release_ex(resolved_path, false); + + return new_op_array; +} + +ZEND_API zend_class_entry *zend_perform_class_map_autoload(zend_string *class_name, zend_string *lc_name) +{ + if (!autoloader_class_map) { + return zend_perform_class_autoload(class_name, lc_name); + } + + zval *class_file_path = zend_hash_find_deref(autoloader_class_map, class_name); + /* An entry has been found in the class map */ + if (class_file_path) { + ZEND_ASSERT(Z_TYPE_P(class_file_path) == IS_STRING); + + zend_op_array *op_array = zend_autoload_execute_file(Z_STR_P(class_file_path)); + if (op_array != NULL && op_array != ZEND_FAKE_OP_ARRAY) { + destroy_op_array(op_array); + efree_size(op_array, sizeof(zend_op_array)); + } + + if (EG(exception)) { + return NULL; + } + + zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name); + if (EXPECTED(ce)) { + return ce; + } + + /* if the item is in the classmap it must be valid after including the file */ + zend_throw_error(NULL, "Error during autoloading from classmap. Entry \"%s\" failed to load the class from \"%s\" (Class undefined after file included)", + ZSTR_VAL(class_name), Z_STRVAL_P(class_file_path)); + return NULL; + } + + + return zend_perform_class_autoload(class_name, lc_name); +} + +/* Needed for compatibility with spl_register_autoload() */ +ZEND_API void zend_register_class_autoloader(zend_fcall_info *fci, zend_fcall_info_cache *fcc, bool prepend) +{ + if (!autoloader_class_autoload_functions) { + ALLOC_HASHTABLE(autoloader_class_autoload_functions); + zend_hash_init(autoloader_class_autoload_functions, 1, NULL, zend_autoload_callback_zval_destroy, false); + /* Initialize as non-packed hash table for prepend functionality. */ + zend_hash_real_init_mixed(autoloader_class_autoload_functions); + } + + if (!ZEND_FCC_INITIALIZED(*fcc)) { + ZEND_ASSERT(fci && ZEND_FCI_INITIALIZED(*fci) && "FCI Must be provided if the callable is a trampoline"); + /* Call trampoline has been cleared by zpp. Refetch it, because we want to deal + * with it ourselves. It is important that it is not refetched on every call, + * because calls may occur from different scopes. */ + zend_is_callable_ex(&fci->function_name, NULL, 0, NULL, fcc, NULL); + } + + if (fcc->function_handler->type == ZEND_INTERNAL_FUNCTION && + fcc->function_handler->internal_function.handler == zif_autoload_call_class) { + zend_argument_value_error(1, "must not be the autoload_call_class() function"); + return; + } + + /* If function is already registered, don't do anything */ + if (autoload_find_registered_function(autoloader_class_autoload_functions, fcc)) { + /* Release call trampoline */ + zend_release_fcall_info_cache(fcc); + return; + } + + zend_fcall_info_cache *entry = emalloc(sizeof(zend_fcall_info_cache)); + zend_fcc_dup(entry, fcc); + zend_hash_next_index_insert_ptr(autoloader_class_autoload_functions, entry); + if (prepend && zend_hash_num_elements(autoloader_class_autoload_functions) > 1) { + /* Move the newly created element to the head of the hashtable */ + HT_MOVE_TAIL_TO_HEAD(autoloader_class_autoload_functions); + } +} + +// TODO USERLAND FUNCTIONS, maybe namespace them? +/* Register given function as a class autoloader */ +ZEND_FUNCTION(autoload_register_class) +{ + bool prepend = false; + zend_fcall_info fci; + zend_fcall_info_cache fcc; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_FUNC(fci, fcc) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(prepend) + ZEND_PARSE_PARAMETERS_END(); + + zend_register_class_autoloader(&fci, &fcc, prepend); +} + +static bool zend_check_map_is_valid(const HashTable *map) { + zend_string *name; + zval *zval_path; + + if (zend_hash_num_elements(map) == 0) { + zend_argument_must_not_be_empty_error(1); + return false; + } + + ZEND_HASH_FOREACH_STR_KEY_VAL(map, name, zval_path) { + if (!name || ZSTR_LEN(name) == 0 || !zend_is_valid_class_name(name)) { + zend_argument_value_error(1, "key \"%s\" is not a valid class name", name ? ZSTR_VAL(name) : ""); + return false; + } + if (Z_TYPE_P(zval_path) != IS_STRING) { + zend_argument_type_error(1, "path for class \"%s\" must be of type string", ZSTR_VAL(name)); + return false; + } + if (Z_STRLEN_P(zval_path) == 0) { + zend_argument_value_error(1, "path for class \"%s\" must not be empty", ZSTR_VAL(name)); + return false; + } + if (zend_str_has_nul_byte(Z_STR_P(zval_path))) { + zend_argument_value_error(1, "path for class \"%s\" must not contain null bytes", ZSTR_VAL(name)); + return false; + } + } ZEND_HASH_FOREACH_END(); + + return true; +} + +ZEND_FUNCTION(autoload_register_class_map) +{ + HashTable *class_map; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_HT(class_map) + ZEND_PARSE_PARAMETERS_END(); + + if (UNEXPECTED(!zend_check_map_is_valid(class_map))) { + RETURN_THROWS(); + } + + autoloader_class_map = zend_array_dup(class_map); + zend_autoload_class = zend_perform_class_map_autoload; +} + +ZEND_FUNCTION(autoload_unregister_class) +{ + zend_fcall_info fci; + zend_fcall_info_cache fcc; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc) + ZEND_PARSE_PARAMETERS_END(); + + if (fcc.function_handler->type == ZEND_INTERNAL_FUNCTION && + fcc.function_handler->internal_function.handler == zif_autoload_call_class) { + zend_error(E_DEPRECATED, + "Using autoload_call_class() as a callback for autoload_unregister_class() is deprecated," + " to remove all registered autoloaders, call autoload_unregister_class()" + " for all values returned from autoload_list_class()"); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } + // Don't destroy the hash table, as we might be iterating over it right now. + if (autoloader_class_autoload_functions) { + zend_hash_clean(autoloader_class_autoload_functions); + } + RETURN_TRUE; + } + + if (!autoloader_class_autoload_functions) { + /* Release trampoline */ + zend_release_fcall_info_cache(&fcc); + RETURN_FALSE; + } + ZEND_ASSERT(autoloader_class_autoload_functions); + + Bucket *p = autoload_find_registered_function(autoloader_class_autoload_functions, &fcc); + /* Release trampoline */ + zend_release_fcall_info_cache(&fcc); + + if (p) { + zend_hash_del_bucket(autoloader_class_autoload_functions, p); + RETURN_TRUE; + } + + RETURN_FALSE; +} + +/* Try all registered class autoloader functions to load the requested class */ +ZEND_FUNCTION(autoload_call_class) +{ + zend_string *class_name; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) { + RETURN_THROWS(); + } + + zend_string *lc_name = zend_string_tolower(class_name); + zend_perform_class_autoload(class_name, lc_name); + zend_string_release(lc_name); +} + +/* Return all registered class autoloader functions */ +ZEND_FUNCTION(autoload_list_class) +{ + zend_fcall_info_cache *func_info; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + if (!autoloader_class_autoload_functions) { + RETURN_EMPTY_ARRAY(); + } + + array_init(return_value); + + ZEND_HASH_FOREACH_PTR(autoloader_class_autoload_functions, func_info) { + zval tmp; + zend_get_callable_zval_from_fcc(func_info, &tmp); + add_next_index_zval(return_value, &tmp); + } ZEND_HASH_FOREACH_END(); +} + +void zend_autoload_shutdown(void) +{ + if (autoloader_class_autoload_functions) { + zend_hash_destroy(autoloader_class_autoload_functions); + FREE_HASHTABLE(autoloader_class_autoload_functions); + autoloader_class_autoload_functions = NULL; + } + if (autoloader_class_map) { + zend_array_release(autoloader_class_map); + autoloader_class_map = NULL; + } +} diff --git a/Zend/zend_autoload.h b/Zend/zend_autoload.h new file mode 100644 index 0000000000000..e0964a71f6435 --- /dev/null +++ b/Zend/zend_autoload.h @@ -0,0 +1,33 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Gina Peter Banyard | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_API.h" +#include "zend_hash.h" + +ZEND_FUNCTION(autoload_register_class); +ZEND_FUNCTION(autoload_register_class_map); +ZEND_FUNCTION(autoload_unregister_class); +ZEND_FUNCTION(autoload_call_class); +ZEND_FUNCTION(autoload_list_class); + +ZEND_API zend_class_entry *zend_perform_class_autoload(zend_string *class_name, zend_string *lc_name); +ZEND_API zend_class_entry *zend_perform_class_map_autoload(zend_string *class_name, zend_string *lc_name); +ZEND_API void zend_autoload_callback_zval_destroy(zval *entry); +ZEND_API void zend_register_class_autoloader(zend_fcall_info *fci, zend_fcall_info_cache *fcc, bool prepend); +void zend_autoload_shutdown(void); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index eab2a03990112..cded569e87614 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -29,12 +29,15 @@ #include "zend_extensions.h" #include "zend_closures.h" #include "zend_generators.h" +#include "zend_autoload.h" #include "zend_builtin_functions_arginfo.h" #include "zend_smart_str.h" /* }}} */ ZEND_MINIT_FUNCTION(core) { /* {{{ */ + zend_autoload_class = zend_perform_class_autoload; + zend_register_default_classes(); zend_standard_class_def = register_class_stdClass(); diff --git a/Zend/zend_builtin_functions.stub.php b/Zend/zend_builtin_functions.stub.php index 9b2267b531eb2..50d594d62bbf6 100644 --- a/Zend/zend_builtin_functions.stub.php +++ b/Zend/zend_builtin_functions.stub.php @@ -217,3 +217,13 @@ function gc_disable(): void {} * @refcount 1 */ function gc_status(): array {} + +function autoload_register_class(callable $callback, bool $prepend = false): void {} + +function autoload_register_class_map(array $classes): void {} + +function autoload_unregister_class(callable $callback): bool {} + +function autoload_call_class(string $class): void {} + +function autoload_list_class(): array {} diff --git a/Zend/zend_builtin_functions_arginfo.h b/Zend/zend_builtin_functions_arginfo.h index 17484eb03f253..275819c3391fa 100644 --- a/Zend/zend_builtin_functions_arginfo.h +++ b/Zend/zend_builtin_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 9b49f527064695c812cd204d9efc63c13681d942 */ + * Stub hash: aa235167ada4497f50840ba5c73434b3a59388fa */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_clone, 0, 1, IS_OBJECT, 0) ZEND_ARG_TYPE_INFO(0, object, IS_OBJECT, 0) @@ -233,6 +233,25 @@ ZEND_END_ARG_INFO() #define arginfo_gc_status arginfo_func_get_args +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_autoload_register_class, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, prepend, _IS_BOOL, 0, "false") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_autoload_register_class_map, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, classes, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_autoload_unregister_class, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, callback, IS_CALLABLE, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_autoload_call_class, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, class, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_autoload_list_class arginfo_func_get_args + ZEND_FRAMELESS_FUNCTION(property_exists, 2); static const zend_frameless_function_info frameless_function_infos_property_exists[] = { @@ -310,6 +329,11 @@ ZEND_FUNCTION(gc_enabled); ZEND_FUNCTION(gc_enable); ZEND_FUNCTION(gc_disable); ZEND_FUNCTION(gc_status); +ZEND_FUNCTION(autoload_register_class); +ZEND_FUNCTION(autoload_register_class_map); +ZEND_FUNCTION(autoload_unregister_class); +ZEND_FUNCTION(autoload_call_class); +ZEND_FUNCTION(autoload_list_class); static const zend_function_entry ext_functions[] = { ZEND_FE(clone, arginfo_clone) @@ -377,6 +401,11 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(gc_enable, arginfo_gc_enable) ZEND_FE(gc_disable, arginfo_gc_disable) ZEND_FE(gc_status, arginfo_gc_status) + ZEND_FE(autoload_register_class, arginfo_autoload_register_class) + ZEND_FE(autoload_register_class_map, arginfo_autoload_register_class_map) + ZEND_FE(autoload_unregister_class, arginfo_autoload_unregister_class) + ZEND_FE(autoload_call_class, arginfo_autoload_call_class) + ZEND_FE(autoload_list_class, arginfo_autoload_list_class) ZEND_FE_END }; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 920c702785ca4..ba69115f61f86 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -35,7 +35,8 @@ ZEND_API extern void (*zend_execute_ex)(zend_execute_data *execute_data); ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value); /* The lc_name may be stack allocated! */ -ZEND_API extern zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name); +ZEND_API extern zend_class_entry *(*zend_autoload_class)(zend_string *name, zend_string *lc_name); +ZEND_API extern zend_function *(*zend_autoload_function)(zend_string *name, zend_string *lc_name); void init_executor(void); void shutdown_executor(void); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 54ddcd48f2d3f..8c3f9d1fafa7a 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -39,6 +39,7 @@ #include "zend_observer.h" #include "zend_call_stack.h" #include "zend_frameless_function.h" +#include "zend_autoload.h" #ifdef HAVE_SYS_TIME_H #include #endif @@ -51,7 +52,7 @@ ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data); ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data, zval *return_value); -ZEND_API zend_class_entry *(*zend_autoload)(zend_string *name, zend_string *lc_name); +ZEND_API zend_class_entry *(*zend_autoload_class)(zend_string *name, zend_string *lc_name); #ifdef ZEND_WIN32 ZEND_TLS HANDLE tq_timer = NULL; @@ -452,6 +453,8 @@ void shutdown_executor(void) /* {{{ */ zend_stream_shutdown(); } zend_end_try(); + /* Shutdown autoloader prior to releasing values as it may hold references to objects */ + zend_autoload_shutdown(); zend_shutdown_executor_values(fast_shutdown); zend_weakrefs_shutdown(); @@ -1238,7 +1241,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string * return NULL; } - if (!zend_autoload) { + if (!zend_autoload_class) { if (!key) { zend_string_release_ex(lc_name, 0); } @@ -1274,7 +1277,7 @@ ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, zend_string * EG(filename_override) = NULL; EG(lineno_override) = -1; zend_exception_save(); - ce = zend_autoload(autoload_name, lc_name); + ce = zend_autoload_class(autoload_name, lc_name); zend_exception_restore(); EG(filename_override) = previous_filename; EG(lineno_override) = previous_lineno; diff --git a/configure.ac b/configure.ac index 77fc8c89cdf40..beeed7eb21115 100644 --- a/configure.ac +++ b/configure.ac @@ -1738,6 +1738,7 @@ PHP_ADD_SOURCES([Zend], m4_normalize([ zend_ast.c zend_atomic.c zend_attributes.c + zend_autoload.c zend_builtin_functions.c zend_call_stack.c zend_closures.c diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 6de7a6d6635af..c1c969991d306 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -34,6 +34,7 @@ #include "spl_heap.h" #include "zend_exceptions.h" #include "zend_interfaces.h" +#include "zend_autoload.h" #include "main/snprintf.h" ZEND_TLS zend_string *spl_autoload_extensions; @@ -351,159 +352,13 @@ PHP_FUNCTION(spl_autoload_extensions) } } /* }}} */ -typedef struct { - zend_function *func_ptr; - zend_object *obj; - zend_object *closure; - zend_class_entry *ce; -} autoload_func_info; - -static void autoload_func_info_destroy(autoload_func_info *alfi) { - if (alfi->obj) { - zend_object_release(alfi->obj); - } - if (alfi->func_ptr && - UNEXPECTED(alfi->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { - zend_string_release_ex(alfi->func_ptr->common.function_name, 0); - zend_free_trampoline(alfi->func_ptr); - } - if (alfi->closure) { - zend_object_release(alfi->closure); - } - efree(alfi); -} - -static void autoload_func_info_zval_dtor(zval *element) -{ - autoload_func_info_destroy(Z_PTR_P(element)); -} - -static autoload_func_info *autoload_func_info_from_fci( - zend_fcall_info *fci, zend_fcall_info_cache *fcc) { - autoload_func_info *alfi = emalloc(sizeof(autoload_func_info)); - alfi->ce = fcc->calling_scope; - alfi->func_ptr = fcc->function_handler; - alfi->obj = fcc->object; - if (alfi->obj) { - GC_ADDREF(alfi->obj); - } - if (Z_TYPE(fci->function_name) == IS_OBJECT) { - alfi->closure = Z_OBJ(fci->function_name); - GC_ADDREF(alfi->closure); - } else { - alfi->closure = NULL; - } - return alfi; -} - -static bool autoload_func_info_equals( - const autoload_func_info *alfi1, const autoload_func_info *alfi2) { - if (UNEXPECTED( - (alfi1->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) && - (alfi2->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) - )) { - return alfi1->obj == alfi2->obj - && alfi1->ce == alfi2->ce - && alfi1->closure == alfi2->closure - && zend_string_equals(alfi1->func_ptr->common.function_name, alfi2->func_ptr->common.function_name) - ; - } - return alfi1->func_ptr == alfi2->func_ptr - && alfi1->obj == alfi2->obj - && alfi1->ce == alfi2->ce - && alfi1->closure == alfi2->closure; -} - -static zend_class_entry *spl_perform_autoload(zend_string *class_name, zend_string *lc_name) { - if (!spl_autoload_functions) { - return NULL; - } - - /* We don't use ZEND_HASH_MAP_FOREACH here, - * because autoloaders may be added/removed during autoloading. */ - HashPosition pos; - zend_hash_internal_pointer_reset_ex(spl_autoload_functions, &pos); - while (1) { - autoload_func_info *alfi = - zend_hash_get_current_data_ptr_ex(spl_autoload_functions, &pos); - if (!alfi) { - break; - } - - zend_function *func = alfi->func_ptr; - if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { - func = emalloc(sizeof(zend_op_array)); - memcpy(func, alfi->func_ptr, sizeof(zend_op_array)); - zend_string_addref(func->op_array.function_name); - } - - zval param; - ZVAL_STR(¶m, class_name); - zend_call_known_function(func, alfi->obj, alfi->ce, NULL, 1, ¶m, NULL); - if (EG(exception)) { - break; - } - - if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) { - return (zend_class_entry*)ZSTR_GET_CE_CACHE(class_name); - } else { - zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name); - if (ce) { - return ce; - } - } - - zend_hash_move_forward_ex(spl_autoload_functions, &pos); - } - return NULL; -} - -/* {{{ Try all registered autoload function to load the requested class */ -PHP_FUNCTION(spl_autoload_call) -{ - zend_string *class_name; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &class_name) == FAILURE) { - RETURN_THROWS(); - } - - zend_string *lc_name = zend_string_tolower(class_name); - spl_perform_autoload(class_name, lc_name); - zend_string_release(lc_name); -} /* }}} */ - -#define HT_MOVE_TAIL_TO_HEAD(ht) \ - ZEND_ASSERT(!HT_IS_PACKED(ht)); \ - do { \ - Bucket tmp = (ht)->arData[(ht)->nNumUsed-1]; \ - memmove((ht)->arData + 1, (ht)->arData, \ - sizeof(Bucket) * ((ht)->nNumUsed - 1)); \ - (ht)->arData[0] = tmp; \ - zend_hash_rehash(ht); \ - } while (0) - -static Bucket *spl_find_registered_function(autoload_func_info *find_alfi) { - if (!spl_autoload_functions) { - return NULL; - } - - autoload_func_info *alfi; - ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) { - if (autoload_func_info_equals(alfi, find_alfi)) { - return _p; - } - } ZEND_HASH_FOREACH_END(); - return NULL; -} - /* {{{ Register given function as autoloader */ PHP_FUNCTION(spl_autoload_register) { bool do_throw = 1; bool prepend = 0; zend_fcall_info fci = {0}; - zend_fcall_info_cache fcc; - autoload_func_info *alfi; + zend_fcall_info_cache fcc = {0}; ZEND_PARSE_PARAMETERS_START(0, 3) Z_PARAM_OPTIONAL @@ -517,137 +372,19 @@ PHP_FUNCTION(spl_autoload_register) "spl_autoload_register() will always throw"); } - if (!spl_autoload_functions) { - ALLOC_HASHTABLE(spl_autoload_functions); - zend_hash_init(spl_autoload_functions, 1, NULL, autoload_func_info_zval_dtor, 0); - /* Initialize as non-packed hash table for prepend functionality. */ - zend_hash_real_init_mixed(spl_autoload_functions); - } - /* If first arg is not null */ if (ZEND_FCI_INITIALIZED(fci)) { - if (!fcc.function_handler) { - /* Call trampoline has been cleared by zpp. Refetch it, because we want to deal - * with it ourselves. It is important that it is not refetched on every call, - * because calls may occur from different scopes. */ - zend_is_callable_ex(&fci.function_name, NULL, IS_CALLABLE_SUPPRESS_DEPRECATIONS, NULL, &fcc, NULL); - } - - if (fcc.function_handler->type == ZEND_INTERNAL_FUNCTION && - fcc.function_handler->internal_function.handler == zif_spl_autoload_call) { - zend_argument_value_error(1, "must not be the spl_autoload_call() function"); - RETURN_THROWS(); - } - - alfi = autoload_func_info_from_fci(&fci, &fcc); - if (UNEXPECTED(alfi->func_ptr == &EG(trampoline))) { - zend_function *copy = emalloc(sizeof(zend_op_array)); - - memcpy(copy, alfi->func_ptr, sizeof(zend_op_array)); - alfi->func_ptr->common.function_name = NULL; - alfi->func_ptr = copy; - } + zend_register_class_autoloader(&fci, &fcc, prepend); } else { - alfi = emalloc(sizeof(autoload_func_info)); - alfi->func_ptr = zend_hash_str_find_ptr( - CG(function_table), "spl_autoload", sizeof("spl_autoload") - 1); - alfi->obj = NULL; - alfi->ce = NULL; - alfi->closure = NULL; - } - - if (spl_find_registered_function(alfi)) { - autoload_func_info_destroy(alfi); - RETURN_TRUE; - } - - zend_hash_next_index_insert_ptr(spl_autoload_functions, alfi); - if (prepend && spl_autoload_functions->nNumOfElements > 1) { - /* Move the newly created element to the head of the hashtable */ - HT_MOVE_TAIL_TO_HEAD(spl_autoload_functions); + /* Pass the zend_function * of the internal pointer directly */ + fcc.function_handler = zend_hash_str_find_ptr(CG(function_table), "spl_autoload", strlen("spl_autoload")); + zend_register_class_autoloader(NULL, &fcc, prepend); } + /* Return true to maintain BC */ RETURN_TRUE; } /* }}} */ -/* {{{ Unregister given function as autoloader */ -PHP_FUNCTION(spl_autoload_unregister) -{ - zend_fcall_info fci; - zend_fcall_info_cache fcc; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_FUNC(fci, fcc) - ZEND_PARSE_PARAMETERS_END(); - - if (fcc.function_handler && zend_string_equals_literal( - fcc.function_handler->common.function_name, "spl_autoload_call")) { - php_error_docref(NULL, E_DEPRECATED, - "Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated," - " to remove all registered autoloaders, call spl_autoload_unregister()" - " for all values returned from spl_autoload_functions()"); - if (UNEXPECTED(EG(exception))) { - RETURN_THROWS(); - } - if (spl_autoload_functions) { - /* Don't destroy the hash table, as we might be iterating over it right now. */ - zend_hash_clean(spl_autoload_functions); - } - RETURN_TRUE; - } - - if (!fcc.function_handler) { - /* Call trampoline has been cleared by zpp. Refetch it, because we want to deal - * with it ourselves. It is important that it is not refetched on every call, - * because calls may occur from different scopes. */ - zend_is_callable_ex(&fci.function_name, NULL, 0, NULL, &fcc, NULL); - } - - autoload_func_info *alfi = autoload_func_info_from_fci(&fci, &fcc); - Bucket *p = spl_find_registered_function(alfi); - autoload_func_info_destroy(alfi); - if (p) { - zend_hash_del_bucket(spl_autoload_functions, p); - RETURN_TRUE; - } - - RETURN_FALSE; -} /* }}} */ - -/* {{{ Return all registered autoloader functions */ -PHP_FUNCTION(spl_autoload_functions) -{ - autoload_func_info *alfi; - - if (zend_parse_parameters_none() == FAILURE) { - RETURN_THROWS(); - } - - array_init(return_value); - if (spl_autoload_functions) { - ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) { - if (alfi->closure) { - GC_ADDREF(alfi->closure); - add_next_index_object(return_value, alfi->closure); - } else if (alfi->func_ptr->common.scope) { - zval tmp; - - array_init(&tmp); - if (alfi->obj) { - GC_ADDREF(alfi->obj); - add_next_index_object(&tmp, alfi->obj); - } else { - add_next_index_str(&tmp, zend_string_copy(alfi->ce->name)); - } - add_next_index_str(&tmp, zend_string_copy(alfi->func_ptr->common.function_name)); - add_next_index_zval(return_value, &tmp); - } else { - add_next_index_str(return_value, zend_string_copy(alfi->func_ptr->common.function_name)); - } - } ZEND_HASH_FOREACH_END(); - } -} /* }}} */ - /* {{{ Return hash id for given object */ PHP_FUNCTION(spl_object_hash) { @@ -725,8 +462,6 @@ PHP_MINFO_FUNCTION(spl) /* {{{ PHP_MINIT_FUNCTION(spl) */ PHP_MINIT_FUNCTION(spl) { - zend_autoload = spl_perform_autoload; - PHP_MINIT(spl_exceptions)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(spl_iterators)(INIT_FUNC_ARGS_PASSTHRU); PHP_MINIT(spl_array)(INIT_FUNC_ARGS_PASSTHRU); diff --git a/ext/spl/php_spl.stub.php b/ext/spl/php_spl.stub.php index d3b5d44f11d1e..c1a71ce46f999 100644 --- a/ext/spl/php_spl.stub.php +++ b/ext/spl/php_spl.stub.php @@ -25,14 +25,17 @@ function class_uses($object_or_class, bool $autoload = true): array|false {} function spl_autoload(string $class, ?string $file_extensions = null): void {} +/** @alias autoload_call_class */ function spl_autoload_call(string $class): void {} function spl_autoload_extensions(?string $file_extensions = null): string {} +/** @alias autoload_list_class */ function spl_autoload_functions(): array {} function spl_autoload_register(?callable $callback = null, bool $throw = true, bool $prepend = false): bool {} +/** @alias autoload_unregister_class */ function spl_autoload_unregister(callable $callback): bool {} /** diff --git a/ext/spl/php_spl_arginfo.h b/ext/spl/php_spl_arginfo.h index 68c71fc524bc5..97ca4e7ea7667 100644 --- a/ext/spl/php_spl_arginfo.h +++ b/ext/spl/php_spl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 21ec2dcca99c85c90afcd319da76016a9f678dc2 */ + * Stub hash: 92f8ab4833e20330385f597cc62349d7ee23d1ca */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_implements, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_INFO(0, object_or_class) @@ -65,11 +65,11 @@ ZEND_FUNCTION(class_implements); ZEND_FUNCTION(class_parents); ZEND_FUNCTION(class_uses); ZEND_FUNCTION(spl_autoload); -ZEND_FUNCTION(spl_autoload_call); +ZEND_FUNCTION(autoload_call_class); ZEND_FUNCTION(spl_autoload_extensions); -ZEND_FUNCTION(spl_autoload_functions); +ZEND_FUNCTION(autoload_list_class); ZEND_FUNCTION(spl_autoload_register); -ZEND_FUNCTION(spl_autoload_unregister); +ZEND_FUNCTION(autoload_unregister_class); ZEND_FUNCTION(spl_classes); ZEND_FUNCTION(spl_object_hash); ZEND_FUNCTION(spl_object_id); @@ -82,11 +82,11 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(class_parents, arginfo_class_parents) ZEND_FE(class_uses, arginfo_class_uses) ZEND_FE(spl_autoload, arginfo_spl_autoload) - ZEND_FE(spl_autoload_call, arginfo_spl_autoload_call) + ZEND_FALIAS(spl_autoload_call, autoload_call_class, arginfo_spl_autoload_call) ZEND_FE(spl_autoload_extensions, arginfo_spl_autoload_extensions) - ZEND_FE(spl_autoload_functions, arginfo_spl_autoload_functions) + ZEND_FALIAS(spl_autoload_functions, autoload_list_class, arginfo_spl_autoload_functions) ZEND_FE(spl_autoload_register, arginfo_spl_autoload_register) - ZEND_FE(spl_autoload_unregister, arginfo_spl_autoload_unregister) + ZEND_FALIAS(spl_autoload_unregister, autoload_unregister_class, arginfo_spl_autoload_unregister) ZEND_FE(spl_classes, arginfo_spl_classes) ZEND_FE(spl_object_hash, arginfo_spl_object_hash) ZEND_FE(spl_object_id, arginfo_spl_object_id) diff --git a/ext/spl/tests/bug40091.phpt b/ext/spl/tests/bug40091.phpt deleted file mode 100644 index 3bb1bbf15238b..0000000000000 --- a/ext/spl/tests/bug40091.phpt +++ /dev/null @@ -1,41 +0,0 @@ ---TEST-- -Bug #40091 (issue with spl_autoload_register() and 2 instances of the same class) ---FILE-- - ---EXPECT-- -Array -( - [0] => Array - ( - [0] => MyAutoloader Object - ( - ) - - [1] => autoload - ) - - [1] => Array - ( - [0] => MyAutoloader Object - ( - ) - - [1] => autoload - ) - -) diff --git a/ext/spl/tests/bug44144.phpt b/ext/spl/tests/bug44144.phpt deleted file mode 100644 index 7dbcf1e636719..0000000000000 --- a/ext/spl/tests/bug44144.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -Bug #44144 (spl_autoload_functions() should return object instance when appropriate) ---FILE-- - ---EXPECTF-- -array(1) { - [0]=> - array(2) { - [0]=> - object(Foo)#%d (0) { - } - [1]=> - string(15) "nonstaticMethod" - } -} diff --git a/ext/spl/tests/bug48023.phpt b/ext/spl/tests/bug48023.phpt deleted file mode 100644 index e42e2f4f03cde..0000000000000 --- a/ext/spl/tests/bug48023.phpt +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Bug #48023 (spl_autoload_register didn't addref closures) ---FILE-- - -===DONE=== ---EXPECTF-- -Fatal error: Uncaught Error: Class "Foo" not found in %s:%d -Stack trace: -#0 {main} - thrown in %s on line %d diff --git a/ext/spl/tests/bug48493.phpt b/ext/spl/tests/bug48493.phpt deleted file mode 100644 index d0be7f8ec71f0..0000000000000 --- a/ext/spl/tests/bug48493.phpt +++ /dev/null @@ -1,26 +0,0 @@ ---TEST-- -SPL: Bug #48493 spl_autoload_unregister() can't handle prepended functions ---FILE-- - ---EXPECT-- -array(2) { - [0]=> - string(9) "autoload1" - [1]=> - string(9) "autoload2" -} -array(1) { - [0]=> - string(9) "autoload1" -} diff --git a/ext/spl/tests/bug61697.phpt b/ext/spl/tests/bug61697.phpt deleted file mode 100644 index 458bba66638b2..0000000000000 --- a/ext/spl/tests/bug61697.phpt +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -Bug #61697 (spl_autoload_functions returns lambda functions incorrectly) ---FILE-- - ---EXPECT-- -Array -( -) diff --git a/ext/spl/tests/bug71204.phpt b/ext/spl/tests/bug71204.phpt deleted file mode 100644 index 3669597a08448..0000000000000 --- a/ext/spl/tests/bug71204.phpt +++ /dev/null @@ -1,21 +0,0 @@ ---TEST-- -Bug #71204 (segfault if clean spl_autoload_funcs while autoloading ) ---FILE-- - ---EXPECTF-- -Deprecated: spl_autoload_unregister(): Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated, to remove all registered autoloaders, call spl_autoload_unregister() for all values returned from spl_autoload_functions() in %s on line %d - -Fatal error: Uncaught Error: Class "A" not found in %s:%d -Stack trace: -#0 {main} - thrown in %sbug71204.php on line %d diff --git a/ext/spl/tests/bug75049.phpt b/ext/spl/tests/bug75049.phpt deleted file mode 100644 index 85e3ef12ca7a6..0000000000000 --- a/ext/spl/tests/bug75049.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Bug #75049 (spl_autoload_unregister can't handle spl_autoload_functions results) ---FILE-- - ---EXPECT-- -11110 diff --git a/ext/spl/tests/spl_autoload_002.phpt b/ext/spl/tests/spl_autoload_002.phpt index 2739e56e3bed1..aaa117399361f 100644 --- a/ext/spl/tests/spl_autoload_002.phpt +++ b/ext/spl/tests/spl_autoload_002.phpt @@ -57,7 +57,7 @@ array(2) { string(16) "SplAutoloadTest2" } -Deprecated: spl_autoload_unregister(): Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated, to remove all registered autoloaders, call spl_autoload_unregister() for all values returned from spl_autoload_functions() in %s on line %d +Deprecated: Using autoload_call_class() as a callback for autoload_unregister_class() is deprecated, to remove all registered autoloaders, call autoload_unregister_class() for all values returned from autoload_list_class() in %s on line %d array(0) { } array(1) { diff --git a/ext/spl/tests/spl_autoload_004.phpt b/ext/spl/tests/spl_autoload_004.phpt deleted file mode 100644 index 8e1eafc37a5d9..0000000000000 --- a/ext/spl/tests/spl_autoload_004.phpt +++ /dev/null @@ -1,40 +0,0 @@ ---TEST-- -SPL: spl_autoload() with static methods ---INI-- -include_path=. ---FILE-- - ---EXPECT-- -array(1) { - [0]=> - array(2) { - [0]=> - string(12) "MyAutoLoader" - [1]=> - string(8) "autoLoad" - } -} -MyAutoLoader::autoLoad(TestClass) -bool(false) diff --git a/ext/spl/tests/spl_autoload_005.phpt b/ext/spl/tests/spl_autoload_005.phpt deleted file mode 100644 index 0f2c5ed2c3024..0000000000000 --- a/ext/spl/tests/spl_autoload_005.phpt +++ /dev/null @@ -1,49 +0,0 @@ ---TEST-- -SPL: spl_autoload() with methods ---INI-- -include_path=. ---FILE-- -getMessage() . \PHP_EOL; -} - -// and - -$myAutoLoader = new MyAutoLoader(); - -spl_autoload_register(array($myAutoLoader, 'autoLoad')); -spl_autoload_register(array($myAutoLoader, 'autoThrow')); - -try -{ - var_dump(class_exists("TestClass", true)); -} -catch(Exception $e) -{ - echo 'Exception: ' . $e->getMessage() . "\n"; -} - -?> ---EXPECT-- -spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, non-static method MyAutoLoader::autoLoad() cannot be called statically -MyAutoLoader::autoLoad(TestClass) -MyAutoLoader::autoThrow(TestClass) -Exception: Unavailable diff --git a/ext/spl/tests/spl_autoload_009.phpt b/ext/spl/tests/spl_autoload_009.phpt deleted file mode 100644 index f12fd0af7e709..0000000000000 --- a/ext/spl/tests/spl_autoload_009.phpt +++ /dev/null @@ -1,23 +0,0 @@ ---TEST-- -SPL: spl_autoload() and friends ---INI-- -include_path=. ---FILE-- - ---EXPECTF-- -%stestclass.inc -%stestclass.class.inc -bool(true) diff --git a/ext/spl/tests/spl_autoload_010.phpt b/ext/spl/tests/spl_autoload_010.phpt deleted file mode 100644 index 3b0754d8dfa97..0000000000000 --- a/ext/spl/tests/spl_autoload_010.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -SPL: spl_autoload() and prepend ---INI-- -include_path=. ---FILE-- - $name\n"; -} -function autoloadB($name) { - echo "B -> $name\n"; -} -function autoloadC($name) { - echo "C -> $name\n"; - class C{} -} - -spl_autoload_register('autoloadA'); -spl_autoload_register('autoloadB', true, true); -spl_autoload_register('autoloadC'); - -new C; -?> ---EXPECT-- -B -> C -A -> C -C -> C diff --git a/ext/spl/tests/spl_autoload_013.phpt b/ext/spl/tests/spl_autoload_013.phpt deleted file mode 100644 index b9b6f6571f320..0000000000000 --- a/ext/spl/tests/spl_autoload_013.phpt +++ /dev/null @@ -1,55 +0,0 @@ ---TEST-- -SPL: spl_autoload_functions() with closures and invocables ---FILE-- -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()); - -?> ---EXPECTF-- -array(3) { - [0]=> - object(Closure)#%d (4) { - ["name"]=> - string(%d) "{closure:%s:%d}" - ["file"]=> - string(%d) "%s" - ["line"]=> - int(%d) - ["parameter"]=> - array(1) { - ["$class"]=> - string(10) "" - } - } - [1]=> - object(Autoloader)#%d (1) { - ["dir":"Autoloader":private]=> - string(2) "d1" - } - [2]=> - object(Autoloader)#%d (1) { - ["dir":"Autoloader":private]=> - string(2) "d2" - } -} diff --git a/ext/spl/tests/spl_autoload_014.phpt b/ext/spl/tests/spl_autoload_014.phpt deleted file mode 100644 index 3c7cc38f63e37..0000000000000 --- a/ext/spl/tests/spl_autoload_014.phpt +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -SPL: spl_autoload_unregister() with closures and invocables ---FILE-- -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; - -?> ---EXPECT-- -closure called with class TestX -Autoloader('d1') called with TestX -WorkingAutoloader() called with TestX -WorkingAutoloader() called with TestY diff --git a/ext/spl/tests/spl_autoload_bug48541.phpt b/ext/spl/tests/spl_autoload_bug48541.phpt deleted file mode 100644 index acdf36aa71d10..0000000000000 --- a/ext/spl/tests/spl_autoload_bug48541.phpt +++ /dev/null @@ -1,37 +0,0 @@ ---TEST-- -SPL: spl_autoload_register() Bug #48541: registering multiple closures fails with memleaks ---FILE-- -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; -?> ---EXPECT-- -a called -a2 called -b called -foo diff --git a/ext/spl/tests/spl_autoload_call_basic.phpt b/ext/spl/tests/spl_autoload_call_basic.phpt deleted file mode 100644 index 2bd65c22be4ba..0000000000000 --- a/ext/spl/tests/spl_autoload_call_basic.phpt +++ /dev/null @@ -1,18 +0,0 @@ ---TEST-- -spl_autoload_call() function - basic test for spl_autoload_call() ---CREDITS-- -Jean-Marc Fontaine -# Alter Way Contribution Day 2011 ---FILE-- - ---EXPECTF-- -%stestclass.class.inc -bool(true) diff --git a/ext/spl/tests/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt b/ext/spl/tests/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt index 943d80ae25377..a0e2a9b95e57e 100644 --- a/ext/spl/tests/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt +++ b/ext/spl/tests/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt @@ -11,4 +11,4 @@ try { ?> --EXPECT-- -spl_autoload_register(): Argument #1 ($callback) must not be the spl_autoload_call() function +spl_autoload_register(): Argument #1 ($callback) must not be the autoload_call_class() function diff --git a/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt b/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt index 867a67e6eb526..8217ed17d4288 100644 --- a/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt +++ b/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt @@ -7,6 +7,6 @@ var_dump(spl_autoload_unregister("spl_autoload_call")); Done --EXPECTF-- -Deprecated: spl_autoload_unregister(): Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated, to remove all registered autoloaders, call spl_autoload_unregister() for all values returned from spl_autoload_functions() in %s on line %d +Deprecated: Using autoload_call_class() as a callback for autoload_unregister_class() is deprecated, to remove all registered autoloaders, call autoload_unregister_class() for all values returned from autoload_list_class() in %s on line %d bool(true) Done diff --git a/win32/build/config.w32 b/win32/build/config.w32 index 403f0aa6efbfe..aefcfb5f82474 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -241,7 +241,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \ zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c \ zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_observer.c zend_system_id.c \ zend_enum.c zend_fibers.c zend_atomic.c zend_hrtime.c zend_frameless_function.c zend_property_hooks.c \ - zend_lazy_objects.c"); + zend_lazy_objects.c zend_autoload.c"); ADD_SOURCES("Zend\\Optimizer", "zend_optimizer.c pass1.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dfg.c dfa_pass.c zend_ssa.c zend_inference.c zend_func_info.c zend_call_graph.c zend_dump.c escape_analysis.c compact_vars.c dce.c sccp.c scdf.c"); var PHP_ASSEMBLER = PATH_PROG({