-
Notifications
You must be signed in to change notification settings - Fork 3k
/
inconsistencies
205 lines (138 loc) · 6.28 KB
/
inconsistencies
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
<h2>Inconsistencies between PHP and HipHop</h2>
1. Arithmetic, arrays, and foreach loops
(1) Arithmetic
In PHP, the addition, subtraction, or multiplication of two integers will
produce a floating-point value if the result overflows the integer type. In
Hiphop, the addition, subtraction, or multiplication of two integers will
always produce an integer value; if the result overflows the integer type, the
high bits of the result will be discarded ("wrap-around").
(2) Next free integer key for arrays
Arrays contain a hidden field called the "NextFreeElement" field that tracks
what integer key should be used when a new element is appended. In PHP, when an
array is copied the NextFreeElement field of the new array is recomputed based
on the keys it currently contains. In HipHop, when an array is copied the new
array's NextFreeElement field is set to the same value as the original array's
NextFreeElement field.
(3) Array internal cursors
In PHP, if an array's internal cursor points to the position past the last
element and then a copy of the array is made, the copy will have its internal
cursor reset to point at the first element. In HipHop, when a copy of an array
is made, the copy's internal cursor will always point to the same position that
the original array's internal cursor pointed to.
(4) Foreach by value
In PHP, foreach by value will modify the array's internal cursor under certain
circumstances. In HipHop, foreach by value will never modify the array's
internal cursor.
(5) Foreach by reference
In PHP, the behavior of a foreach by reference loop can be unpredictable if
during iteration the next element of the array is unset, or if the array
variable is assigned to directly or through a reference, or if copy-on-write
causes the array to be copied. For such cases, HipHop's behavior may differ
from PHP.
2. Classes and objects
(1) Exceptions thrown from destructors
In HipHop, exceptions and fatals thrown from destructors will be swallowed
while logging an error. Effectively, there is a try/catch enclosing the body
of the __destruct method. These exceptions are catchable in PHP outside of the
__destruct method.
(2) __destruct behavior at end of request
In PHP, if an object is still live at the end of a request, its __destruct
method is invoked. The HipHop static compiler (hphpc) does not do this.
By default, HipHop VM (hhvm) matches hphpc's behavior for live objects at the
end of the request. The EnableObjDestructCall runtime option can be used to
make hhvm invoke the __destruct method for objects that are live at the end of
the request.
(3) Exceptions thrown from __toString()
PHP doesn't allow them. HipHop does. Also, PHP doesn't allow __toString() to
return anything other than a string. HipHop will just convert return value to
string.
(4) __call/__callStatic() handling
These 2 examples give inconsistent results in PHP 5.3:
<?php
class B {
}
class G extends B {
function __call($name, $arguments) { var_dump('G');}
function f4missing($a) {
B::f4missing(5); // __call checking happened at B
}
}
$g = new G();
$g->f4missing(3);
<?php
class B {
function __call($name, $arguments) { var_dump('B');}
}
class G extends B {
function __call($name, $arguments) { var_dump('G');}
function f4missing($a) {
B::f4missing(5); // G::__call() was called actually!
}
}
$g = new G();
$g->f4missing(3);
In HipHop, both checking and invocation of __call() happen on class G.
(5) Object internal cursors
In PHP, objects have an internal cursor (similar to the array internal cursor)
that can be used to iterate over the object's properties. In HipHop, objects do
not have internal cursors, and the next(), prev(), current(), key(), reset(),
end(), and each() builtin functions do not support objects.
3. Eval Issues
(1) eval
hphpc only supports eval in limited circumstances.
Example unsupported case: phpt...bug21960
hhvm fully supports eval.
(2) create_function
hphpc only supports create_function with literal arguments.
Example unsupported case: phpt...bug22690
hhvm fully supports create_function.
(3) preg_replace /e
hphpc and hhvm only support preg_replace /e in limited cases.
Example unsupported case: phpt...bug24403
4. $GLOBALS is not an ordinary variable:
In PHP, you can assign to $GLOBALS:
$GLOBALS = 0;
$x = $GLOBALS - 5;
$g = $GLOBALS;
$g['x'] = 3;
In HipHop, this is not allowed or not working.
5. Constants
(1) Dynamically declared constants
hphpc does not support dynamically declared constants, for example:
define($name, $value);
hhvm fully supports dynamically declared constants.
(2) Case-insensitive constants
hphpc and hhvm do not support case-insensitive constants, for example:
define('FOO', 123, true);
6. Misc
(1) function_exists() and class_exists()
Under hphpc, function_exists($funcname) and class_exists($clsname) may give
different results than in PHP. This is because hphpc has all uniquely-named
functions and classes declared by default, unless it is marked as "volatile",
either by a configuration file, or automatically by the compiler recognizing
string literal being used with function_exists or class_exists, for example:
class_exists('MyClass')
hhvm's behavior for function_exists() and class_exists() matches that of PHP.
(2) get_defined_vars() and get_declared_classes()
hphpc and hhvm may return variables/classes in a different order than PHP.
(3) Uninitialized variables
Under hphpc, if an uninitialized variable is being used before it's assigned
with a value, no warning will be raised. Furthermore, the value of the
uninitialized variable may be 0 instead of null if hphpc's static analysis
inferred the variable to be an integer.
hhvm raises warnings when uninitialized variables are read, and the value read
from an uninitialized variable will always be null.
(4) XMLWriter
In PHP, XMLWriter class and its functions returned different types of objects,
<?php
function foo(XMLWriter $w) {}
$obj = new XMLWriter();
foo($obj); // <-- this one is actually okay
$obj2 = xmlwriter_open_memory(); // <-- just not this one
var_dump($obj, $obj2);
foo($obj2);
In HipHop, they are the same.
(5) hphpc has support for PHP namespaces. hhvm currently does not have
support for PHP namespaces.
(6) ReflectionProperty::setAccessible() and ReflectionMethod::setAccessible()
are not currently supported.