1--TEST--
2Lazy objects: Initializer effects are reverted after exception
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    try {
20        $reflector->initializeLazyObject($obj);
21    } catch (Exception $e) {
22        printf("%s\n", $e->getMessage());
23    }
24
25    var_dump($obj);
26    printf("Is lazy: %d\n", $reflector->isUninitializedLazyObject($obj));
27}
28
29$reflector = new ReflectionClass(C::class);
30
31$obj = $reflector->newLazyGhost(function ($obj) {
32    var_dump("initializer");
33    $obj->a = 3;
34    $obj->b = 4;
35    $obj->c = 5;
36    throw new Exception('initializer exception');
37});
38
39test('Ghost', $obj);
40
41$obj = $reflector->newLazyProxy(function ($obj) {
42    var_dump("initializer");
43    $obj->a = 3;
44    $obj->b = 4;
45    $obj->c = 5;
46    throw new Exception('initializer exception');
47});
48
49// Initializer effects on the proxy are not reverted
50test('Proxy', $obj);
51
52--EXPECTF--
53# Ghost:
54string(11) "initializer"
55initializer exception
56lazy ghost object(C)#%d (1) {
57  ["b"]=>
58  uninitialized(int)
59  ["c"]=>
60  int(0)
61}
62Is lazy: 1
63# Proxy:
64string(11) "initializer"
65initializer exception
66lazy proxy object(C)#%d (3) {
67  ["a"]=>
68  int(3)
69  ["b"]=>
70  int(4)
71  ["c"]=>
72  int(5)
73}
74Is lazy: 1
75