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