1--TEST--
2Lazy objects: Initializer effects are reverted after exception (properties hashtable)
3--FILE--
4<?php
5
6class C {
7    public $a = 1;
8    public int $b = 2;
9    public int $c;
10}
11
12function test(string $name, object $obj) {
13    $reflector = new ReflectionClass(C::class);
14
15    printf("# %s:\n", $name);
16
17    (new ReflectionProperty(C::class, 'c'))->setRawValueWithoutLazyInitialization($obj, 0);
18
19    // Builds properties hashtable
20    var_dump(get_mangled_object_vars($obj));
21
22    try {
23        $reflector->initializeLazyObject($obj);
24    } catch (Exception $e) {
25        printf("%s\n", $e->getMessage());
26    }
27
28    var_dump($obj);
29    printf("Is lazy: %d\n", $reflector->isUninitializedLazyObject($obj));
30}
31
32$reflector = new ReflectionClass(C::class);
33
34$obj = $reflector->newLazyGhost(function ($obj) {
35    var_dump("initializer");
36    $obj->a = 3;
37    $obj->b = 4;
38    $obj->c = 5;
39    throw new Exception('initializer exception');
40});
41
42test('Ghost', $obj);
43
44$obj = $reflector->newLazyProxy(function ($obj) {
45    var_dump("initializer");
46    $obj->a = 3;
47    $obj->b = 4;
48    $obj->c = 5;
49    throw new Exception('initializer exception');
50});
51
52// Initializer effects on the proxy are not reverted
53test('Proxy', $obj);
54
55--EXPECTF--
56# Ghost:
57array(1) {
58  ["c"]=>
59  int(0)
60}
61string(11) "initializer"
62initializer exception
63lazy ghost object(C)#%d (1) {
64  ["b"]=>
65  uninitialized(int)
66  ["c"]=>
67  int(0)
68}
69Is lazy: 1
70# Proxy:
71array(1) {
72  ["c"]=>
73  int(0)
74}
75string(11) "initializer"
76initializer exception
77lazy proxy object(C)#%d (3) {
78  ["a"]=>
79  int(3)
80  ["b"]=>
81  int(4)
82  ["c"]=>
83  int(5)
84}
85Is lazy: 1
86