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