mirror of
https://github.com/php/php-src.git
synced 2025-08-20 09:24:05 +02:00
Merge branch 'master' into openssl_error_store
This commit is contained in:
commit
c2b90805e8
796 changed files with 121373 additions and 44590 deletions
|
@ -165,7 +165,7 @@ User Functions/Methods Naming Conventions
|
||||||
'foobar'
|
'foobar'
|
||||||
'foo_bar'
|
'foo_bar'
|
||||||
|
|
||||||
Internal Function Naming Convensions
|
Internal Function Naming Conventions
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
1. Functions that are part of the external API should be named
|
1. Functions that are part of the external API should be named
|
||||||
|
|
|
@ -79,7 +79,7 @@ The next few rules are more of a technical nature::
|
||||||
should be noted in both PHP-5.4/NEWS and PHP-5.5/NEWS but
|
should be noted in both PHP-5.4/NEWS and PHP-5.5/NEWS but
|
||||||
not master, which is not a public released version yet.
|
not master, which is not a public released version yet.
|
||||||
|
|
||||||
3. Do not commit multiple file and dump all messages in one commit. If you
|
3. Do not commit multiple files and dump all messages in one commit. If you
|
||||||
modified several unrelated files, commit each group separately and
|
modified several unrelated files, commit each group separately and
|
||||||
provide a nice commit message for each one. See example below.
|
provide a nice commit message for each one. See example below.
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ It is recommended to do so a couple of days before the packaging day, to
|
||||||
have enough time to investigate failures, communicate with the authors and
|
have enough time to investigate failures, communicate with the authors and
|
||||||
commit the fixes.
|
commit the fixes.
|
||||||
The RM for the branch is also responsible for keeping the CI green on
|
The RM for the branch is also responsible for keeping the CI green on
|
||||||
ongoing bases between the releases. Check the CI status for your branch
|
ongoing basis between the releases. Check the CI status for your branch
|
||||||
periodically and resolve the failures ASAP. See more in:
|
periodically and resolve the failures ASAP. See more in:
|
||||||
https://wiki.php.net/rfc/travis_ci
|
https://wiki.php.net/rfc/travis_ci
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ team (Bjori) on hand.
|
||||||
|
|
||||||
6. Verify the tags to be extra sure everything was tagged properly.
|
6. Verify the tags to be extra sure everything was tagged properly.
|
||||||
|
|
||||||
7. Moving extensions from/to PECL requires write acces to the destination.
|
7. Moving extensions from/to PECL requires write access to the destination.
|
||||||
Most developers should have this.
|
Most developers should have this.
|
||||||
|
|
||||||
Moving extensions from php-src to PECL
|
Moving extensions from php-src to PECL
|
||||||
|
@ -271,8 +271,8 @@ to upgrade.
|
||||||
10. Wait an hour or two, then send a mail to php-announce@lists.php.net,
|
10. Wait an hour or two, then send a mail to php-announce@lists.php.net,
|
||||||
php-general@lists.php.net and internals@lists.php.net with a text similar to
|
php-general@lists.php.net and internals@lists.php.net with a text similar to
|
||||||
http://news.php.net/php.internals/17222.
|
http://news.php.net/php.internals/17222.
|
||||||
Please make sure that the mail to php-announce@ is its own completely seperate email.
|
Please make sure that the mail to php-announce@ is its own completely separate email.
|
||||||
This is to make sure that repiles to the announcement on php-general@ or internals@
|
This is to make sure that replies to the announcement on php-general@ or internals@
|
||||||
will not accidentally hit the php-announce@ mailinglist.
|
will not accidentally hit the php-announce@ mailinglist.
|
||||||
|
|
||||||
Re-releasing the same version (or -pl)
|
Re-releasing the same version (or -pl)
|
||||||
|
@ -309,6 +309,6 @@ to upgrade.
|
||||||
5. Wait an hour or two, then send a mail to php-announce@lists.php.net,
|
5. Wait an hour or two, then send a mail to php-announce@lists.php.net,
|
||||||
php-general@lists.php.net and internals@lists.php.net with a text similar to
|
php-general@lists.php.net and internals@lists.php.net with a text similar to
|
||||||
the news entry.
|
the news entry.
|
||||||
Please make sure that the mail to php-announce@ is its own completely seperate email.
|
Please make sure that the mail to php-announce@ is its own completely separate email.
|
||||||
This is to make sure that repiles to the announcement on php-general@ or internals@
|
This is to make sure that replies to the announcement on php-general@ or internals@
|
||||||
will not accidentally hit the php-announce@ mailinglist.
|
will not accidentally hit the php-announce@ mailinglist.
|
||||||
|
|
|
@ -10,7 +10,7 @@ Pull Requests
|
||||||
=============
|
=============
|
||||||
PHP accepts pull requests via github. Discussions are done on github, but
|
PHP accepts pull requests via github. Discussions are done on github, but
|
||||||
depending on the topic can also be relayed to the official PHP developer
|
depending on the topic can also be relayed to the official PHP developer
|
||||||
mailinglist internals@lists.php.net.
|
mailing list internals@lists.php.net.
|
||||||
|
|
||||||
New features require an RFC and must be accepted by the developers.
|
New features require an RFC and must be accepted by the developers.
|
||||||
See https://wiki.php.net/rfc and https://wiki.php.net/rfc/voting for more
|
See https://wiki.php.net/rfc and https://wiki.php.net/rfc/voting for more
|
||||||
|
|
837
UPGRADING
837
UPGRADING
|
@ -1,4 +1,4 @@
|
||||||
PHP 7.0 UPGRADE NOTES
|
PHP 7.1 UPGRADE NOTES
|
||||||
|
|
||||||
1. Backward Incompatible Changes
|
1. Backward Incompatible Changes
|
||||||
2. New Features
|
2. New Features
|
||||||
|
@ -19,799 +19,158 @@
|
||||||
1. Backward Incompatible Changes
|
1. Backward Incompatible Changes
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
Language changes
|
- Core:
|
||||||
================
|
. 'void' can no longer be used as the name of a class, interface, or trait.
|
||||||
|
This applies to declarations, class_alias() and use statements.
|
||||||
Changes to variable handling
|
. (int), intval() where $base is 10 or unspecified, settype(), decbin(),
|
||||||
----------------------------
|
decoct(), dechex(), integer operators and other conversions now always
|
||||||
|
respect scientific notation in numeric strings.
|
||||||
* Indirect variable, property and method references are now interpreted with
|
(RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic)
|
||||||
left-to-right semantics. Some examples:
|
. The ASCII 0x7F Delete control character is no longer permitted in unquoted
|
||||||
|
identifiers in source code.
|
||||||
$$foo['bar']['baz'] // interpreted as ($$foo)['bar']['baz']
|
. The following functions may no longer be called dynamically using $func(),
|
||||||
$foo->$bar['baz'] // interpreted as ($foo->$bar)['baz']
|
call_user_func(), array_map() or similar:
|
||||||
$foo->$bar['baz']() // interpreted as ($foo->$bar)['baz']()
|
. extract()
|
||||||
Foo::$bar['baz']() // interpreted as (Foo::$bar)['baz']()
|
. compact()
|
||||||
|
. get_defined_vars()
|
||||||
To restore the previous behavior add explicit curly braces:
|
. func_get_args()
|
||||||
|
. func_get_arg()
|
||||||
${$foo['bar']['baz']}
|
. func_num_args()
|
||||||
$foo->{$bar['baz']}
|
. parse_str() with one argument
|
||||||
$foo->{$bar['baz']}()
|
. mb_parse_str() with one argument
|
||||||
Foo::{$bar['baz']}()
|
. assert() with a string argument
|
||||||
|
(RFC: https://wiki.php.net/rfc/forbid_dynamic_scope_introspection)
|
||||||
* The global keyword now only accepts simple variables. Instead of
|
. If the error_log is set to syslog, the PHP error levels are mapped to the
|
||||||
|
syslog error levels. This brings finer differentiation in the error logs
|
||||||
global $$foo->bar;
|
in contrary to the previous approach where all the errors are loggged with
|
||||||
|
the notice level only.
|
||||||
it is now required to write the following:
|
|
||||||
|
|
||||||
global ${$foo->bar};
|
|
||||||
|
|
||||||
* Parentheses around variables or function calls no longer have any influence
|
|
||||||
on behavior. For example the following code, where the result of a function
|
|
||||||
call is passed to a by-reference function
|
|
||||||
|
|
||||||
function getArray() { return [1, 2, 3]; }
|
|
||||||
|
|
||||||
$last = array_pop(getArray());
|
|
||||||
// Strict Standards: Only variables should be passed by reference
|
|
||||||
$last = array_pop((getArray()));
|
|
||||||
// Strict Standards: Only variables should be passed by reference
|
|
||||||
|
|
||||||
will now throw a strict standards error regardless of whether parentheses
|
|
||||||
are used. Previously no notice was generated in the second case.
|
|
||||||
|
|
||||||
* Array elements or object properties that are automatically created during
|
|
||||||
by-reference assignments will now result in a different order. For example
|
|
||||||
|
|
||||||
$array = [];
|
|
||||||
$array["a"] =& $array["b"];
|
|
||||||
$array["b"] = 1;
|
|
||||||
var_dump($array);
|
|
||||||
|
|
||||||
now results in the array ["a" => 1, "b" => 1], while previously the result
|
|
||||||
was ["b" => 1, "a" => 1];
|
|
||||||
|
|
||||||
Relevant RFCs:
|
|
||||||
* https://wiki.php.net/rfc/uniform_variable_syntax
|
|
||||||
* https://wiki.php.net/rfc/abstract_syntax_tree
|
|
||||||
|
|
||||||
Changes to list()
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
* list() will no longer assign variables in reverse order. For example
|
|
||||||
|
|
||||||
list($array[], $array[], $array[]) = [1, 2, 3];
|
|
||||||
var_dump($array);
|
|
||||||
|
|
||||||
will now result in $array == [1, 2, 3] rather than [3, 2, 1]. Note that only
|
|
||||||
the **order** of the assignments changed, but the assigned values stay the
|
|
||||||
same. E.g. a normal usage like
|
|
||||||
|
|
||||||
list($a, $b, $c) = [1, 2, 3];
|
|
||||||
// $a = 1; $b = 2; $c = 3;
|
|
||||||
|
|
||||||
will retain its current behavior.
|
|
||||||
|
|
||||||
* Empty list() assignments are no longer allowed. As such all of the following
|
|
||||||
are invalid:
|
|
||||||
|
|
||||||
list() = $a;
|
|
||||||
list(,,) = $a;
|
|
||||||
list($x, list(), $y) = $a;
|
|
||||||
|
|
||||||
* list() no longer supports unpacking strings (while previously this was only
|
|
||||||
supported in some cases). The code
|
|
||||||
|
|
||||||
$string = "xy";
|
|
||||||
list($x, $y) = $string;
|
|
||||||
|
|
||||||
will now result in $x == null and $y == null (without notices) instead of
|
|
||||||
$x == "x" and $y == "y". Furthermore list() is now always guaranteed to
|
|
||||||
work with objects implementing ArrayAccess, e.g.
|
|
||||||
|
|
||||||
list($a, $b) = (object) new ArrayObject([0, 1]);
|
|
||||||
|
|
||||||
will now result in $a == 0 and $b == 1. Previously both $a and $b were null.
|
|
||||||
|
|
||||||
Relevant RFCs:
|
|
||||||
* https://wiki.php.net/rfc/abstract_syntax_tree#changes_to_list
|
|
||||||
* https://wiki.php.net/rfc/fix_list_behavior_inconsistency
|
|
||||||
|
|
||||||
Changes to foreach
|
|
||||||
------------------
|
|
||||||
|
|
||||||
* Iteration with foreach() no longer has any effect on the internal array
|
|
||||||
pointer, which can be accessed through the current()/next()/etc family of
|
|
||||||
functions. For example
|
|
||||||
|
|
||||||
$array = [0, 1, 2];
|
|
||||||
foreach ($array as &$val) {
|
|
||||||
var_dump(current($array));
|
|
||||||
}
|
|
||||||
|
|
||||||
will now print the value int(0) three times. Previously the output was int(1),
|
|
||||||
int(2) and bool(false).
|
|
||||||
|
|
||||||
* When iterating arrays by-value, foreach will now always operate on a copy of
|
|
||||||
the array, as such changes to the array during iteration will not influence
|
|
||||||
iteration behavior. For example
|
|
||||||
|
|
||||||
$array = [0, 1, 2];
|
|
||||||
$ref =& $array; // Necessary to trigger the old behavior
|
|
||||||
foreach ($array as $val) {
|
|
||||||
var_dump($val);
|
|
||||||
unset($array[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
will now print all three elements (0 1 2), while previously the second element
|
|
||||||
1 was skipped (0 2).
|
|
||||||
|
|
||||||
* When iterating arrays by-reference, modifications to the array will continue
|
|
||||||
to influence the iteration. However PHP will now do a better job of
|
|
||||||
maintaining a correct position in a number of cases. E.g. appending to an
|
|
||||||
array during by-reference iteration
|
|
||||||
|
|
||||||
$array = [0];
|
|
||||||
foreach ($array as &$val) {
|
|
||||||
var_dump($val);
|
|
||||||
$array[1] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
will now iterate over the appended element as well. As such the output of this
|
|
||||||
example will now be "int(0) int(1)", while previously it was only "int(0)".
|
|
||||||
|
|
||||||
* Iteration of plain (non-Traversable) objects by-value or by-reference will
|
|
||||||
behave like by-reference iteration of arrays. This matches the previous
|
|
||||||
behavior apart from the more accurate position management mentioned in the
|
|
||||||
previous point.
|
|
||||||
|
|
||||||
* Iteration of Traversable objects remains unchanged.
|
|
||||||
|
|
||||||
Relevant RFC: https://wiki.php.net/rfc/php7_foreach
|
|
||||||
|
|
||||||
Changes to parameter handling
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
* It is no longer possible to define two function parameters with the same name.
|
|
||||||
For example, the following method will trigger a compile-time error:
|
|
||||||
|
|
||||||
public function foo($a, $b, $unused, $unused) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
Code like this should be changed to use distinct parameter names, for example:
|
|
||||||
|
|
||||||
public function foo($a, $b, $unused1, $unused2) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
* The func_get_arg() and func_get_args() functions will no longer return the
|
|
||||||
original value that was passed to a parameter and will instead provide the
|
|
||||||
current value (which might have been modified). For example
|
|
||||||
|
|
||||||
function foo($x) {
|
|
||||||
$x++;
|
|
||||||
var_dump(func_get_arg(0));
|
|
||||||
}
|
|
||||||
foo(1);
|
|
||||||
|
|
||||||
will now print "2" instead of "1". This code should be changed to either
|
|
||||||
perform modifications only after calling func_get_arg(s)
|
|
||||||
|
|
||||||
function foo($x) {
|
|
||||||
var_dump(func_get_arg(0));
|
|
||||||
$x++;
|
|
||||||
}
|
|
||||||
|
|
||||||
or avoid modifying the parameters altogether:
|
|
||||||
|
|
||||||
function foo($x) {
|
|
||||||
$newX = $x + 1;
|
|
||||||
var_dump(func_get_arg(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
* Similarly exception backtraces will no longer display the original value that
|
|
||||||
was passed to a function and show the modified value instead. For example
|
|
||||||
|
|
||||||
function foo($x) {
|
|
||||||
$x = 42;
|
|
||||||
throw new Exception;
|
|
||||||
}
|
|
||||||
foo("string");
|
|
||||||
|
|
||||||
will now result in the stack trace
|
|
||||||
|
|
||||||
Stack trace:
|
|
||||||
#0 file.php(4): foo(42)
|
|
||||||
#1 {main}
|
|
||||||
|
|
||||||
while previously it was:
|
|
||||||
|
|
||||||
Stack trace:
|
|
||||||
#0 file.php(4): foo('string')
|
|
||||||
#1 {main}
|
|
||||||
|
|
||||||
While this should not impact runtime behavior of your code, it is worthwhile
|
|
||||||
to be aware of this difference for debugging purposes.
|
|
||||||
|
|
||||||
The same limitation also applies to debug_backtrace() and other functions
|
|
||||||
inspecting function arguments.
|
|
||||||
|
|
||||||
Relevant RFC: https://wiki.php.net/phpng
|
|
||||||
|
|
||||||
Changes to integer handling
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
* Invalid octal literals (containing digits larger than 7) now produce compile
|
|
||||||
errors. For example, the following is no longer valid:
|
|
||||||
|
|
||||||
$i = 0781; // 8 is not a valid octal digit!
|
|
||||||
|
|
||||||
Previously the invalid digits (and any following valid digits) were simply
|
|
||||||
ignored. As such $i previously held the value 7, because the last two digits
|
|
||||||
were silently discarded.
|
|
||||||
|
|
||||||
* Bitwise shifts by negative numbers will now throw an ArithmeticError:
|
|
||||||
|
|
||||||
var_dump(1 >> -1);
|
|
||||||
// ArithmeticError: Bit shift by negative number
|
|
||||||
|
|
||||||
* Left bitwise shifts by a number of bits beyond the bit width of an integer
|
|
||||||
will always result in 0:
|
|
||||||
|
|
||||||
var_dump(1 << 64); // int(0)
|
|
||||||
|
|
||||||
Previously the behavior of this code was dependent on the used CPU
|
|
||||||
architecture. For example on x86 (including x86-64) the result was int(1),
|
|
||||||
because the shift operand was wrapped.
|
|
||||||
|
|
||||||
* Similarly right bitwise shifts by a number of bits beyond the bit width of an
|
|
||||||
integer will always result in 0 or -1 (depending on sign):
|
|
||||||
|
|
||||||
var_dump(1 >> 64); // int(0)
|
|
||||||
var_dump(-1 >> 64); // int(-1)
|
|
||||||
|
|
||||||
Relevant RFC: https://wiki.php.net/rfc/integer_semantics
|
|
||||||
|
|
||||||
Changes to string handling
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
* Strings that contain hexadecimal numbers are no longer considered to be
|
|
||||||
numeric and don't receive special treatment anymore. Some examples of the
|
|
||||||
new behavior:
|
|
||||||
|
|
||||||
var_dump("0x123" == "291"); // bool(false) (previously true)
|
|
||||||
var_dump(is_numeric("0x123")); // bool(false) (previously true)
|
|
||||||
var_dump("0xe" + "0x1"); // int(0) (previously 16)
|
|
||||||
|
|
||||||
var_dump(substr("foo", "0x1")); // string(3) "foo" (previously "oo")
|
|
||||||
// Notice: A non well formed numeric value encountered
|
|
||||||
|
|
||||||
filter_var() can be used to check if a string contains a hexadecimal number
|
|
||||||
or convert such a string into an integer:
|
|
||||||
|
|
||||||
$str = "0xffff";
|
|
||||||
$int = filter_var($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
|
|
||||||
if (false === $int) {
|
|
||||||
throw new Exception("Invalid integer!");
|
|
||||||
}
|
|
||||||
var_dump($int); // int(65535)
|
|
||||||
|
|
||||||
* Due to the addition of the Unicode Codepoint Escape Syntax for double-quoted
|
|
||||||
strings and heredocs, "\u{" followed by an invalid sequence will now result in
|
|
||||||
an error:
|
|
||||||
|
|
||||||
$str = "\u{xyz}"; // Fatal error: Invalid UTF-8 codepoint escape sequence
|
|
||||||
|
|
||||||
To avoid this the leading backslash should be escaped:
|
|
||||||
|
|
||||||
$str = "\\u{xyz}"; // Works fine
|
|
||||||
|
|
||||||
However, "\u" without a following { is unaffected. As such the following code
|
|
||||||
won't error and will work the same as before:
|
|
||||||
|
|
||||||
$str = "\u202e"; // Works fine
|
|
||||||
|
|
||||||
Relevant RFCs:
|
|
||||||
* https://wiki.php.net/rfc/remove_hex_support_in_numeric_strings
|
|
||||||
* https://wiki.php.net/rfc/unicode_escape
|
|
||||||
|
|
||||||
Changes to error handling
|
|
||||||
-------------------------
|
|
||||||
|
|
||||||
* There are now two exception classes: Exception and Error. Both classes
|
|
||||||
implement a new interface Throwable. Type hints in exception handling code
|
|
||||||
may need to be changed to account for this.
|
|
||||||
|
|
||||||
* Some fatal errors and recoverable fatal errors now throw an Error instead.
|
|
||||||
As Error is a separate class from Exception, these exceptions will not be
|
|
||||||
caught by existing try/catch blocks.
|
|
||||||
|
|
||||||
For the recoverable fatal errors which have been converted into an exception,
|
|
||||||
it is no longer possible to silently ignore the error from an error handler.
|
|
||||||
In particular, it is no longer possible to ignore type hint failures.
|
|
||||||
|
|
||||||
* Parser errors now generate a ParseError that extends Error. Error
|
|
||||||
handling for eval()s on potentially invalid code should be changed to catch
|
|
||||||
ParseError in addition to the previous return value / error_get_last()
|
|
||||||
based handling.
|
|
||||||
|
|
||||||
* Constructors of internal classes will now always throw an exception on
|
|
||||||
failure. Previously some constructors returned NULL or an unusable object.
|
|
||||||
|
|
||||||
* The error level of some E_STRICT notices has been changed.
|
|
||||||
|
|
||||||
Relevant RFCs:
|
|
||||||
* https://wiki.php.net/rfc/engine_exceptions_for_php7
|
|
||||||
* https://wiki.php.net/rfc/throwable-interface
|
|
||||||
* https://wiki.php.net/rfc/internal_constructor_behaviour
|
|
||||||
* https://wiki.php.net/rfc/reclassify_e_strict
|
|
||||||
|
|
||||||
Other language changes
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
* Removed support for static calls to non-static methods from an incompatible
|
|
||||||
$this context. In this case $this will not be defined, but the call will be
|
|
||||||
allowed with a deprecation notice. An example:
|
|
||||||
|
|
||||||
class A {
|
|
||||||
public function test() { var_dump($this); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: Does NOT extend A
|
|
||||||
class B {
|
|
||||||
public function callNonStaticMethodOfA() { A::test(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
(new B)->callNonStaticMethodOfA();
|
|
||||||
|
|
||||||
// Deprecated: Non-static method A::test() should not be called statically
|
|
||||||
// Notice: Undefined variable $this
|
|
||||||
NULL
|
|
||||||
|
|
||||||
Note that this only applies to calls from an incompatible context. If class B
|
|
||||||
extended from A the call would be allowed without any notices.
|
|
||||||
|
|
||||||
* It is no longer possible to use the following class, interface and trait names
|
|
||||||
(case-insensitive):
|
|
||||||
|
|
||||||
bool
|
|
||||||
int
|
|
||||||
float
|
|
||||||
string
|
|
||||||
null
|
|
||||||
false
|
|
||||||
true
|
|
||||||
|
|
||||||
This applies to class/interface/trait declarations, class_alias() and use
|
|
||||||
statements.
|
|
||||||
|
|
||||||
Furthermore the following class, interface and trait names are now reserved
|
|
||||||
for future use, but do not yet throw an error when used:
|
|
||||||
|
|
||||||
resource
|
|
||||||
object
|
|
||||||
mixed
|
|
||||||
numeric
|
|
||||||
|
|
||||||
* The yield language construct no longer requires parentheses when used in an
|
|
||||||
expression context. It is now a right-associative operator with precedence
|
|
||||||
between the "print" and "=>" operators. This can result in different behavior
|
|
||||||
in some cases, for example:
|
|
||||||
|
|
||||||
echo yield -1;
|
|
||||||
// Was previously interpreted as
|
|
||||||
echo (yield) - 1;
|
|
||||||
// And is now interpreted as
|
|
||||||
echo yield (-1);
|
|
||||||
|
|
||||||
yield $foo or die;
|
|
||||||
// Was previously interpreted as
|
|
||||||
yield ($foo or die);
|
|
||||||
// And is now interpreted as
|
|
||||||
(yield $foo) or die;
|
|
||||||
|
|
||||||
Such cases can always be resolved by adding additional parentheses.
|
|
||||||
|
|
||||||
. Removed ASP (<%) and script (<script language=php>) tags.
|
|
||||||
(RFC: https://wiki.php.net/rfc/remove_alternative_php_tags)
|
|
||||||
. Removed support for assigning the result of new by reference.
|
|
||||||
. Removed support for scoped calls to non-static methods from an incompatible
|
|
||||||
$this context. See details in https://wiki.php.net/rfc/incompat_ctx.
|
|
||||||
. Removed support for #-style comments in ini files. Use ;-style comments
|
|
||||||
instead.
|
|
||||||
. $HTTP_RAW_POST_DATA is no longer available. Use the php://input stream instead.
|
|
||||||
|
|
||||||
Standard library changes
|
|
||||||
========================
|
|
||||||
|
|
||||||
. substr() now returns an empty string instead of FALSE when the truncation happens on boundaries.
|
|
||||||
. call_user_method() and call_user_method_array() no longer exists.
|
|
||||||
. ob_start() no longer issues an E_ERROR, but instead an E_RECOVERABLE_ERROR in case an
|
|
||||||
output buffer is created in an output buffer handler.
|
|
||||||
. The internal sorting algorithm has been improved, what may result in
|
|
||||||
different sort order of elements that compare as equal.
|
|
||||||
. Removed dl() function on fpm-fcgi.
|
|
||||||
. setcookie() with an empty cookie name now issues a WARNING and doesn't send an empty set-cookie header line anymore.
|
|
||||||
|
|
||||||
Other
|
|
||||||
=====
|
|
||||||
|
|
||||||
- Curl:
|
|
||||||
. Removed support for disabling the CURLOPT_SAFE_UPLOAD option. All curl file
|
|
||||||
uploads must use the curl_file / CURLFile APIs.
|
|
||||||
|
|
||||||
- Date:
|
|
||||||
. Removed $is_dst parameter from mktime() and gmmktime().
|
|
||||||
|
|
||||||
- DBA
|
|
||||||
. dba_delete() now returns false if the key was not found for the inifile
|
|
||||||
handler, too.
|
|
||||||
|
|
||||||
- GMP
|
|
||||||
. Requires libgmp version 4.2 or newer now.
|
|
||||||
. gmp_setbit() and gmp_clrbit() now return FALSE for negative indices, making
|
|
||||||
them consistent with other GMP functions.
|
|
||||||
|
|
||||||
- Intl:
|
|
||||||
. Removed deprecated aliases datefmt_set_timezone_id() and
|
|
||||||
IntlDateFormatter::setTimeZoneID(). Use datefmt_set_timezone() and
|
|
||||||
IntlDateFormatter::setTimeZone() instead.
|
|
||||||
|
|
||||||
- libxml:
|
|
||||||
. Added LIBXML_BIGLINES parser option. It's available starting with libxml 2.9.0
|
|
||||||
and adds suppport for line numbers >16-bit in the error reporting.
|
|
||||||
|
|
||||||
- Mcrypt
|
|
||||||
. Removed deprecated mcrypt_generic_end() alias in favor of
|
|
||||||
mcrypt_generic_deinit().
|
|
||||||
. Removed deprecated mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb()
|
|
||||||
functions in favor of mcrypt_encrypt() and mcrypt_decrypt() with an
|
|
||||||
MCRYPT_MODE_* flag.
|
|
||||||
|
|
||||||
- Session
|
|
||||||
. session_start() accepts all INI settings as array. e.g. ['cache_limiter'=>'private']
|
|
||||||
sets session.cache_limiter=private. It also supports 'read_and_close' which closes
|
|
||||||
session data immediately after read data.
|
|
||||||
. Save handler accepts validate_sid(), update_timestamp() which validates session
|
|
||||||
ID existence, updates timestamp of session data. Compatibility of old user defined
|
|
||||||
save handler is retained.
|
|
||||||
. SessionUpdateTimestampHandlerInterface is added. validateSid(), updateTimestamp()
|
|
||||||
is defined in the interface.
|
|
||||||
. session.lazy_write(default=On) INI setting enables only write session data when
|
|
||||||
session data is updated.
|
|
||||||
|
|
||||||
- Opcache
|
|
||||||
. Removed opcache.load_comments configuration directive. Now doc comments
|
|
||||||
loading costs nothing and always enabled.
|
|
||||||
|
|
||||||
- OpenSSL:
|
|
||||||
. Removed the "rsa_key_size" SSL context option in favor of automatically
|
|
||||||
setting the appropriate size given the negotiated crypto algorithm.
|
|
||||||
. Removed "CN_match" and "SNI_server_name" SSL context options. Use automatic
|
|
||||||
detection or the "peer_name" option instead.
|
|
||||||
|
|
||||||
- PCRE:
|
|
||||||
. Removed support for /e (PREG_REPLACE_EVAL) modifier. Use
|
|
||||||
preg_replace_callback() instead.
|
|
||||||
|
|
||||||
- PDO_pgsql:
|
|
||||||
. Removed PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT attribute in favor of
|
|
||||||
ATTR_EMULATE_PREPARES.
|
|
||||||
|
|
||||||
- Standard:
|
|
||||||
. Removed string category support in setlocale(). Use the LC_* constants
|
|
||||||
instead.
|
|
||||||
. Removed set_magic_quotes_runtime() and its alias magic_quotes_runtime().
|
|
||||||
|
|
||||||
- JSON:
|
- JSON:
|
||||||
. Rejected RFC 7159 incompatible number formats in json_decode string -
|
. When calling json_encode with JSON_UNESCAPED_UNICODE option, U+2028 and
|
||||||
top level (07, 0xff, .1, -.1) and all levels ([1.], [1.e1])
|
U+2029 are escaped.
|
||||||
. Calling json_decode with 1st argument equal to empty PHP string or value that
|
|
||||||
after casting to string is empty string (NULL, FALSE) results in JSON syntax error.
|
|
||||||
|
|
||||||
- Stream:
|
|
||||||
. Removed set_socket_blocking() in favor of its alias stream_set_blocking().
|
|
||||||
|
|
||||||
- XSL:
|
|
||||||
. Removed xsl.security_prefs ini option. Use XsltProcessor::setSecurityPrefs()
|
|
||||||
instead.
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
2. New Features
|
2. New Features
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- Core
|
- Core
|
||||||
. Added group use declarations.
|
. Added void return type, which requires that a function not return a value.
|
||||||
(RFC: https://wiki.php.net/rfc/group_use_declarations)
|
(RFC: https://wiki.php.net/rfc/void_return_type)
|
||||||
. Added null coalesce operator (??).
|
. String offset access now supports negative references, which will be
|
||||||
(RFC: https://wiki.php.net/rfc/isset_ternary)
|
counted from the end of the string.
|
||||||
. Support for strings with length >= 2^31 bytes in 64 bit builds.
|
(RFC: https://wiki.php.net/rfc/negative-string-offsets)
|
||||||
. Closure::call() method added (works only with userland classes).
|
. Added a form of the list() construct where keys can be specified.
|
||||||
. Added \u{xxxxxx} Unicode Codepoint Escape Syntax for double-quoted strings
|
(RFC: https://wiki.php.net/rfc/list_keys)
|
||||||
and heredocs.
|
. Added [] = as alternative construct to list() =.
|
||||||
. define() now supports arrays as constant values, fixing an oversight where
|
(RFC: https://wiki.php.net/rfc/short_list_syntax)
|
||||||
define() did not support arrays yet const syntax did.
|
. Number operators taking numeric strings now emit "A non well formed numeric
|
||||||
. Added the comparison operator (<=>), aka the spaceship operator.
|
value encountered" E_NOTICEs for leading-numeric strings, and "A
|
||||||
(RFC: https://wiki.php.net/rfc/combined-comparison-operator)
|
non-numeric value encountered" E_WARNINGs for non-numeric strings.
|
||||||
. Added the yield from operator for delegating Generators like coroutines.
|
This always applies to the +, -, *, /, **, %, << and >> operators, and
|
||||||
(RFC: https://wiki.php.net/rfc/generator-delegation)
|
their assignment counterparts +=, -=, *=, /=, **=, %=, <<= and >>=.
|
||||||
. Reserved keywords can now be used in various new contexts.
|
For the bitwise operators |, & and ^, and their assignment counterparts
|
||||||
(RFC: https://wiki.php.net/rfc/context_sensitive_lexer)
|
|=, &= and ^=, this only applies where only one operand is a string.
|
||||||
. Added support for scalar type declarations and strict mode using
|
Note that this never applies to the bitwise NOT operator, ~, which does not
|
||||||
declare(strict_types=1) (RFC: https://wiki.php.net/rfc/scalar_type_hints_v5)
|
handle numeric strings, nor to the increment and decrement operators
|
||||||
. Added support for cryptographically secure user land RNG
|
++ and --, which have a unique approach to handling numeric strings.
|
||||||
(RFC: https://wiki.php.net/rfc/easy_userland_csprng)
|
(RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic)
|
||||||
|
|
||||||
- Opcache
|
|
||||||
. Added second level file based opcode cache. It may be enabled by setting
|
|
||||||
opcache.file_cache=<DIR> configuration directive in php.ini. The second
|
|
||||||
level cache may improve performance when SHM is full, at server restart or
|
|
||||||
SHM reset. In addition, it's possibe to use file cache without SHM at all,
|
|
||||||
using opcache.file_cache_only=1 (this may be useful for sharing hosting),
|
|
||||||
and disable file cache consistency check, to speedup loading at the cost of
|
|
||||||
safety, using opcache.file_cache_consistency_checks=0.
|
|
||||||
. Added ability to move PHP code pages (PHP TEXT segment) into HUGE pages.
|
|
||||||
It's possible to enable/disable this feature in php.ini through
|
|
||||||
opcache.huge_code_pages=0/1. OS should be configured to provide huge pages.
|
|
||||||
. Added Windows only opcache.file_cache_fallback=1 ini option, which implies
|
|
||||||
the implemented fallback mechanism. When OPcache was not able to reattach
|
|
||||||
the shared memory segment to the desired address and opcache.file_cache
|
|
||||||
is on, opcache.file_cache_only=1 will be automatically enforced.
|
|
||||||
|
|
||||||
- OpenSSL
|
|
||||||
. Added "alpn_protocols" SSL context option allowing encrypted client/server
|
|
||||||
streams to negotiate alternative protocols using the ALPN TLS extension when
|
|
||||||
built against OpenSSL 1.0.2 or newer. Negotiated protocol information is
|
|
||||||
accessible through stream_get_meta_data() output.
|
|
||||||
|
|
||||||
- Reflection
|
|
||||||
. Added a ReflectionGenerator class (yield from Traces, current file/line,
|
|
||||||
etc.)
|
|
||||||
. Added a ReflectionType class to better support the new return type and
|
|
||||||
scalar type declarations features. The new ReflectionParameter::getType()
|
|
||||||
and ReflectionFunctionAbstract::getReturnType() methods both return an
|
|
||||||
instance of ReflectionType.
|
|
||||||
|
|
||||||
- Stream:
|
|
||||||
. New Windows only stream context options was added to allow blocking reads
|
|
||||||
on pipes. To enable it, pass array("pipe" => array("blocking" => true))
|
|
||||||
when creating the stream context. Be aware, that this option can under
|
|
||||||
circumstances cause dead locks on the pipe buffer. However it can be useful
|
|
||||||
in several CLI use case scenarios.
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
3. Changes in SAPI modules
|
3. Changes in SAPI modules
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- FPM
|
|
||||||
. Fixed bug #65933 (Cannot specify config lines longer than 1024 bytes).
|
|
||||||
. Listen = port now listen on all addresses (IPv6 and IPv4-mapped).
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
4. Deprecated Functionality
|
4. Deprecated Functionality
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- Core
|
|
||||||
. PHP 4 style constructors, where the constructor name is the same as the
|
|
||||||
class name, are now deprecated.
|
|
||||||
. Static calls to non-static methods are now deprecated.
|
|
||||||
|
|
||||||
- OpenSSL
|
|
||||||
. The "capture_session_meta" SSL context option is now deprecated. Meta
|
|
||||||
data concerning active crypto on a stream resource is now accessible
|
|
||||||
through the return result from stream_get_meta_data().
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
5. Changed Functions
|
5. Changed Functions
|
||||||
========================================
|
========================================
|
||||||
|
- get_headers() has an extra parameter which allows passing a custom stream
|
||||||
- unserialize():
|
context.
|
||||||
. Added second parameter for unserialize function
|
- The first $varname argument for getenv() is no longer mandatory, the
|
||||||
(RFC: https://wiki.php.net/rfc/secure_unserialize) allowing to specify
|
current environment variables will be returned as an associative array
|
||||||
acceptable classes:
|
when omitted.
|
||||||
unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
|
- json_encode() accepts new option JSON_UNESCAPED_LINE_TERMINATORS that
|
||||||
|
disables escaping of U+2028 and U+2029 characters when
|
||||||
- proc_open():
|
JSON_UNESCAPED_UNICODE is supplied.
|
||||||
. The maximum number of pipes used by proc_open() was previously limited by
|
- long2ip() accepts integer as parameter now
|
||||||
hardcoded value of 16. This limit is now removed and the number of pipes is
|
- pg_last_notice() accepts optional long parameter to specify operation.
|
||||||
effectively limited by the amount of memory available to PHP.
|
PGSQL_NOTICE_LAST - Get last notice (Default)
|
||||||
. New Windows only configuration option "blocking_pipes" can be used to
|
PGSQL_NOTICE_ALL - Get all stored notices
|
||||||
force blocking reads on child process pipes. This covers several
|
PGSQL_NOTICE_CLEAR - Remove all stored notices
|
||||||
edge cases in CLI usage however can lead to dead locks. Also, this
|
It returns empty string or array on successful PGSQL_NOTICE_LAST/ALL calls.
|
||||||
correlates with the new stream context options for pipes.
|
It returned FALSE for empty notice previously.
|
||||||
|
- pg_fetch_all() accepts 2nd optional result type parameter like
|
||||||
- array_column():
|
pg_fetch_row().
|
||||||
The function now supports an array of objects as well as two-dimensional
|
- pg_select() accepts 4th optional result type parameter like pg_fetch_row().
|
||||||
arrays. Only public properties are considered, and objects that make use of
|
- parse_url() is more restrictive now and supports RFC3986.
|
||||||
__get() for dynamic properties must also implement __isset().
|
- unpack() accepts an additional optional $offset argument. '@' format code
|
||||||
|
(that specifes an absolute position) is applyed to input data after
|
||||||
- stream_context_create()
|
the $offset argument.
|
||||||
It accepts now a Windows only configuration
|
- strpos(), stripos(), substr_count(), grapheme_strpos(), grapheme_stripos(),
|
||||||
array("pipe" => array("blocking" => <boolean>)) which forces blocking reads
|
grapheme_extract(), iconv_strpos(), mb_strimwidth(), mb_ereg_search_setpos(),
|
||||||
on pipes. This option should be used carefully because due to the
|
mb_strpos() and mb_stripos() now accept negative string offsets.
|
||||||
platform restrictions dead locks on pipe buffers are possible.
|
- substr_count() and mb_strimwidth() additionally also accept negative length.
|
||||||
|
- file_get_contents() accepts a negative seek offset if the stream is seekable.
|
||||||
- dirname()
|
- tempnam() throws a notice when failing back to the system temp dir.
|
||||||
A new optional argument ($levels) allow to go up various times
|
|
||||||
dirname(dirname($foo)) => dirname($foo, 2);
|
|
||||||
|
|
||||||
- debug_zval_dump
|
|
||||||
It prints now "int" instead of "long", and "float" instead of "double".
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
6. New Functions
|
6. New Functions
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- GMP
|
|
||||||
. Added gmp_random_seed().
|
|
||||||
|
|
||||||
- PCRE:
|
|
||||||
. Added preg_replace_callback_array function
|
|
||||||
(RFC: https://wiki.php.net/rfc/preg_replace_callback_array)
|
|
||||||
|
|
||||||
- Standard
|
|
||||||
. Added intdiv() function for integer division.
|
|
||||||
. Added error_clear_last() function to reset error state.
|
|
||||||
|
|
||||||
- Zip:
|
|
||||||
. Added ZipArchive::setCompressionIndex() and ZipArchive::setCompressionName()
|
|
||||||
for setting the compression method.
|
|
||||||
|
|
||||||
- Zlib:
|
|
||||||
. Added deflate_init(), deflate_add(), inflate_init(), inflate_add()
|
|
||||||
functions allowing incremental/streaming compression/decompression.
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
7. New Classes and Interfaces
|
7. New Classes and Interfaces
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- ReflectionGenerator
|
|
||||||
- ReflectionType
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
8. Removed Extensions and SAPIs
|
8. Removed Extensions and SAPIs
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- sapi/aolserver
|
|
||||||
- sapi/apache
|
|
||||||
- sapi/apache_hooks
|
|
||||||
- sapi/apache2filter
|
|
||||||
- sapi/caudium
|
|
||||||
- sapi/continuity
|
|
||||||
- sapi/isapi
|
|
||||||
- sapi/milter
|
|
||||||
- sapi/nsapi
|
|
||||||
- sapi/phttpd
|
|
||||||
- sapi/pi3web
|
|
||||||
- sapi/roxen
|
|
||||||
- sapi/thttpd
|
|
||||||
- sapi/tux
|
|
||||||
- sapi/webjames
|
|
||||||
- ext/mssql
|
|
||||||
- ext/mysql
|
|
||||||
- ext/sybase_ct
|
|
||||||
- ext/ereg
|
|
||||||
|
|
||||||
For more details see
|
|
||||||
|
|
||||||
https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts
|
|
||||||
https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7
|
|
||||||
|
|
||||||
NOTE: NSAPI was not voted in the RFC, however it was removed afterwards. It turned
|
|
||||||
out, that the corresponding SDK isn't available anymore.
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
9. Other Changes to Extensions
|
9. Other Changes to Extensions
|
||||||
========================================
|
========================================
|
||||||
|
- SQLite3:
|
||||||
- Mhash
|
. Upgraded bundled SQLite lib to 3.13.0
|
||||||
Mhash is not an extension anymore, use function_exists("mhash") to check whether
|
|
||||||
it is avaliable.
|
|
||||||
|
|
||||||
- GD
|
|
||||||
The bundled libgd requires libwebp instead of libvpx for the WebP functionality.
|
|
||||||
|
|
||||||
- Openssl
|
|
||||||
minimum supported OpenSSL version series was raised to 0.9.8
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
10. New Global Constants
|
10. New Global Constants
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- Core
|
- JSON:
|
||||||
. PHP_INT_MIN added.
|
. JSON_UNESCAPED_LINE_TERMINATORS
|
||||||
|
|
||||||
- PCRE
|
- Pgsql:
|
||||||
. This error constant is added to signal errors due to stack size limitations
|
PGSQL_NOTICE_LAST
|
||||||
when PCRE JIT support is enabled:
|
PGSQL_NOTICE_ALL
|
||||||
. PREG_JIT_STACKLIMIT_ERROR
|
PGSQL_NOTICE_CLEAR
|
||||||
|
|
||||||
- Zlib
|
|
||||||
. These constants are added to control flush behavior with the new
|
|
||||||
incremental deflate_add() and inflate_add() functions:
|
|
||||||
. ZLIB_NO_FLUSH
|
|
||||||
. ZLIB_PARTIAL_FLUSH
|
|
||||||
. ZLIB_SYNC_FLUSH
|
|
||||||
. ZLIB_FULL_FLUSH
|
|
||||||
. ZLIB_BLOCK
|
|
||||||
. ZLIB_FINISH
|
|
||||||
|
|
||||||
- GD
|
|
||||||
. T1Lib support removed, thus lifting the optional dependency on T1Lib, the
|
|
||||||
following is therefore not available anymore:
|
|
||||||
|
|
||||||
Functions:
|
|
||||||
- imagepsbbox()
|
|
||||||
- imagepsencodefont()
|
|
||||||
- imagepsextendedfont()
|
|
||||||
- imagepsfreefont()
|
|
||||||
- imagepsloadfont()
|
|
||||||
- imagepsslantfont()
|
|
||||||
- imagepstext()
|
|
||||||
|
|
||||||
Resources:
|
|
||||||
- 'gd PS font'
|
|
||||||
- 'gd PS encoding'
|
|
||||||
|
|
||||||
- Zip
|
|
||||||
. Filename encoding flags, as of 7.0.8
|
|
||||||
- ZipArchive::FL_ENC_GUESS
|
|
||||||
- ZipArchive::FL_ENC_RAW
|
|
||||||
- ZipArchive::FL_ENC_STRICT
|
|
||||||
- ZipArchive::FL_ENC_UTF_8
|
|
||||||
- ZipArchive::FL_ENC_CP437
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
11. Changes to INI File Handling
|
11. Changes to INI File Handling
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- Core
|
|
||||||
. Removed asp_tags ini directive. Trying to enable it will result in a fatal
|
|
||||||
error.
|
|
||||||
. Removed always_populate_raw_post_data ini directive.
|
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
12. Windows Support
|
12. Windows Support
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- Core
|
- Core:
|
||||||
. Support for native 64 bit integers in 64 bit builds.
|
. Support for ftok()
|
||||||
. Support for large files in 64 bit builds.
|
|
||||||
. Support for getrusage()
|
|
||||||
|
|
||||||
- ftp
|
- FCGI
|
||||||
. The ftp extension is always shipped shared
|
. PHP_FCGI_CHILDREN is respected. If this environment variable is defined,
|
||||||
. For SSL support, the dependency on the openssl extension was abolished. Instead
|
the first php-fcgi.exe process will exec the specified number of children.
|
||||||
it depends alone on the openssl library. If it's present at the compile time,
|
Those will share the same TCP socket.
|
||||||
ftp_ssl_connect() is enabled automatically.
|
|
||||||
|
|
||||||
- imap
|
- readline:
|
||||||
. Static building of ext/imap is disabled
|
. The readline extension is supported through the WinEditLine library
|
||||||
|
(http://mingweditline.sourceforge.net/). Thereby, the interactive CLI
|
||||||
|
shell is supported as well (php.exe -a).
|
||||||
|
|
||||||
- odbc
|
It is well known, but nevertheless is worth mentioning again, that
|
||||||
. The odbc extension is always shipped shared
|
the readline extension is not thread safe and will never be. Thus,
|
||||||
|
the usage of it with any true thread safe SAPI (like Apache mod_winnt) is
|
||||||
|
strongely discouraged.
|
||||||
|
|
||||||
========================================
|
========================================
|
||||||
13. Other Changes
|
13. Other Changes
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
- Core
|
|
||||||
. Instead of being undefined and platform-dependent, NaN and Infinity will
|
|
||||||
always be zero when cast to integer.
|
|
||||||
. Calling a method on a non-object now raises a catchable error instead of a
|
|
||||||
fatal error; see: https://wiki.php.net/rfc/catchable-call-to-member-of-non-object
|
|
||||||
. Error messages for zend_parse_parameters, type hints and conversions now
|
|
||||||
always say "integer" and "float" instead of "long" and "double".
|
|
||||||
. Output buffering now continues to work for an aborted connection if
|
|
||||||
ignore_user_abort is set to true.
|
|
||||||
. Zend Extensions API was extended with zend_extension.op_array_persist_calc()
|
|
||||||
and zend_extensions.op_array_persist() handlers. They allow to store (or
|
|
||||||
reset) associated with op_array addition information in Opcache Shared
|
|
||||||
Memory.
|
|
||||||
. zend_internal_function.reserved[] array was introduced to allow association
|
|
||||||
of aditional information with internal functions. In PHP-5 it was possible
|
|
||||||
to use zend_function.op_array.reserved[] even for internal functions, but
|
|
||||||
now we don't allocate extra space.
|
|
||||||
|
|
|
@ -1,25 +1,7 @@
|
||||||
PHP 7.0 INTERNALS UPGRADE NOTES
|
PHP 7.1 INTERNALS UPGRADE NOTES
|
||||||
|
|
||||||
0. Wiki Examples
|
0. Wiki Examples
|
||||||
1. Internal API changes
|
1. Internal API changes
|
||||||
e. New data types
|
|
||||||
f. zend_parse_parameters() specs
|
|
||||||
g. sprintf() formats
|
|
||||||
h. HashTable API
|
|
||||||
i. New portable macros for large file support
|
|
||||||
j. New portable macros for integers
|
|
||||||
k. get_class_entry object handler info
|
|
||||||
l. get_class_name object handler info
|
|
||||||
m. Other portable macros info
|
|
||||||
n. ZEND_ENGINE_2 removal
|
|
||||||
o. Updated final class modifier
|
|
||||||
p. TSRM changes
|
|
||||||
q. gc_collect_cycles() is now hookable
|
|
||||||
r. PDO uses size_t for lengths
|
|
||||||
s. Resource API changes
|
|
||||||
t. Optimized strings concatenation.
|
|
||||||
u. Streams changes
|
|
||||||
v. Sort algorithm changes
|
|
||||||
|
|
||||||
2. Build system changes
|
2. Build system changes
|
||||||
a. Unix build system changes
|
a. Unix build system changes
|
||||||
|
@ -39,219 +21,6 @@ changes. See: https://wiki.php.net/phpng-upgrading
|
||||||
1. Internal API changes
|
1. Internal API changes
|
||||||
========================
|
========================
|
||||||
|
|
||||||
e. New data types
|
|
||||||
|
|
||||||
String
|
|
||||||
|
|
||||||
Besides the old way of accepting the strings with 's', the new 'S' ZPP spec
|
|
||||||
was introduced. It expects an argument of the type zend_string *. String lengths
|
|
||||||
in it are bound to the size_t datatype.
|
|
||||||
|
|
||||||
Integer types
|
|
||||||
|
|
||||||
Integers do no more depend on the firm 'long' type. Instead a platform
|
|
||||||
dependent integer type is used, it is called zend_long. That datatype is
|
|
||||||
defined dynamically to guarantee the consistent 64 bit support. The zval
|
|
||||||
field representing user land integer it bound to zend_long.
|
|
||||||
|
|
||||||
Signed integer is defined as zend_long, unsigned integer as zend_ulong
|
|
||||||
inside Zend.
|
|
||||||
|
|
||||||
Other datatypes
|
|
||||||
|
|
||||||
zend_off_t - portable off_t analogue
|
|
||||||
zend_stat_t - portable 'struct stat' analogue
|
|
||||||
|
|
||||||
These datatypes are declared to be portable across platforms. Thus, direct
|
|
||||||
usage of the functions like fseek, stat, etc. as well as direct usage of
|
|
||||||
off_t and struct stat is strongly not recommended. Instead the portable
|
|
||||||
macros should be used.
|
|
||||||
|
|
||||||
zend_fseek - portable fseek equivalent
|
|
||||||
zend_ftell - portable ftell equivalent
|
|
||||||
zend_lseek - portable lseek equivalent
|
|
||||||
zend_fstat - portable fstat equivalent
|
|
||||||
zend_stat - portable stat equivalent
|
|
||||||
|
|
||||||
f. zend_parse_parameters() specs
|
|
||||||
|
|
||||||
The new spec 'S' introduced, which expects an argument of type zend_string *.
|
|
||||||
The 'l' spec expects a parameter of the type zend_long, not long anymore.
|
|
||||||
The 's' spec expects parameters of the type char * and size_t, no int anymore.
|
|
||||||
|
|
||||||
g. sprintf() formats
|
|
||||||
|
|
||||||
New printf modifier 'p' was implemented to platform independently output zend_long,
|
|
||||||
zend_ulong and php_size_t datatypes. That modifier can be used with 'd', 'u', 'x' and 'o'
|
|
||||||
printf format specs with spprintf, snprintf and the wrapping printf implementations.
|
|
||||||
%pu is sufficient for both zend_ulong and php_size_t. the code using %p spec to output
|
|
||||||
pointer address might need to be enclosed into #ifdef when it unlickily followed by 'd',
|
|
||||||
'u', 'x' or 'o'.
|
|
||||||
|
|
||||||
The only exceptions are the snprintf and zend_sprintf functions yet, because in some cases
|
|
||||||
they can use the implemenations available on the system, not the PHP one. With snprintf the
|
|
||||||
macros ZEND_LONG_FMT and ZEND_ULONG_FMT should be used.
|
|
||||||
|
|
||||||
h. HashTable API
|
|
||||||
|
|
||||||
Datatype for array indexes was changed to zend_ulong, for string keys to zend_string *.
|
|
||||||
|
|
||||||
i. New portable macros for large file support
|
|
||||||
|
|
||||||
Function(s) Alias Comment
|
|
||||||
stat, _stat64 zend_stat for use with zend_stat_t
|
|
||||||
fstat, _fstat64 zend_fstat for use with zend_stat_t
|
|
||||||
lseek, _lseeki64 zend_lseek for use with zend_off_t
|
|
||||||
ftell, _ftelli64 zend_ftell for use with zend_off_t
|
|
||||||
fseek, _fseeki64 zend_fseek for use with zend_off_t
|
|
||||||
|
|
||||||
j. New portable macros for integers
|
|
||||||
|
|
||||||
Function(s) Alias Comment
|
|
||||||
snprintf with "%ld" or "%lld", _ltoa_s, _i64toa_s ZEND_LTOA for use with zend_long
|
|
||||||
atol, atoll, _atoi64 ZEND_ATOL for use with zend_long
|
|
||||||
strtol, strtoll, _strtoi64 ZEND_STRTOL for use with zend_long
|
|
||||||
strtoul, strtoull, _strtoui64 ZEND_STRTOUL for use with zend_long
|
|
||||||
abs, llabs, _abs64 ZEND_ABS for use with zend_long
|
|
||||||
- ZEND_LONG_MAX replaces LONG_MAX where appropriate
|
|
||||||
- ZEND_LONG_MIN replaces LONG_MIN where appropriate
|
|
||||||
- ZEND_ULONG_MAX replaces ULONG_MAX where appropriate
|
|
||||||
- SIZEOF_ZEND_LONG reworked SIZEOF_ZEND_LONG representing the size of zend_long datatype
|
|
||||||
- ZEND_SIZE_MAX Max value of size_t
|
|
||||||
- Z_L casts an integral constant to zend_long
|
|
||||||
- Z_UL casts an integral constant to zend_ulong
|
|
||||||
|
|
||||||
The macro ZEND_ENABLE_ZVAL_LONG64 reveals whether zval operates on 64 or 32 bit integer.
|
|
||||||
|
|
||||||
k. The get_class_entry object handler is no longer available. Instead
|
|
||||||
zend_object.ce is always used.
|
|
||||||
|
|
||||||
l. The get_class_name object handler is now only used for displaying class
|
|
||||||
names in debugging functions like var_dump(). It is no longer used in
|
|
||||||
get_class(), get_parent_class() or similar.
|
|
||||||
|
|
||||||
The handler is now obligatory, no longer accepts a `parent` argument and
|
|
||||||
must return a non-NULL zend_string*, which will be released by the caller.
|
|
||||||
|
|
||||||
m. Other portable macros info
|
|
||||||
|
|
||||||
ZEND_SECURE_ZERO - zeroes chunk of memory
|
|
||||||
ZEND_VALID_SOCKET - validates a php_socket_t variable
|
|
||||||
|
|
||||||
ZEND_FASTCALL is defined to use __vectorcall convention on VS2013 and above
|
|
||||||
ZEND_NORETURN is defined as __declspec(noreturn) on VS
|
|
||||||
|
|
||||||
n. The ZEND_ENGINE_2 macro has been removed. A ZEND_ENGINE_3 macro has been added.
|
|
||||||
|
|
||||||
o. Removed ZEND_ACC_FINAL_CLASS in favour of ZEND_ACC_FINAL, turning final class
|
|
||||||
modifier now a different class entry flag. Update your extensions.
|
|
||||||
|
|
||||||
p. TSRM changes
|
|
||||||
|
|
||||||
The TSRM layer undergone significant changes. It is not necessary anymore to
|
|
||||||
pass the tsrm_ls pointer explicitly. The TSRMLS_* macros should not be used
|
|
||||||
in any new developments.
|
|
||||||
|
|
||||||
The recommended way accessing globals in TS builds is by implementing it
|
|
||||||
to use a local thread unique pointer to the corresponding data pool. These
|
|
||||||
are the new macros that serve to achieve this goal:
|
|
||||||
|
|
||||||
- ZEND_TSRMG - based on TSRMG and if static pointer for data pool access is
|
|
||||||
implemented, will use it
|
|
||||||
- ZEND_TSRMLS_CACHE_EXTERN - to be used in a header shared across multiple
|
|
||||||
C/C++ files
|
|
||||||
- ZEND_TSRMLS_CACHE_DEFINE - to be used in the main extension C/C++ file
|
|
||||||
- ZEND_TSRMLS_CACHE_UPDATE - to be integrated at the top of the globals
|
|
||||||
ctor or RINIT function
|
|
||||||
- ZEND_ENABLE_STATIC_TSRMLS_CACHE - to be used in the config.[m4|w32] for
|
|
||||||
enabling the globals access per thread unique pointer
|
|
||||||
- TSRMLS_CACHE - expands to the variable name which links to the thread
|
|
||||||
unique data pool
|
|
||||||
|
|
||||||
Note that usually it will work without implementing the globals access per
|
|
||||||
a thread unique pointer, however it might cause a slowdown. The reason is
|
|
||||||
that the access model to the extension/SAPI own globals as well as the
|
|
||||||
access to the core globals is determined in the compilation phase depending
|
|
||||||
on whether ZEND_ENABLE_STATIC_TSRMLS_CACHE macro is defined.
|
|
||||||
|
|
||||||
Due to the current compiler evolution state, the TSRMLS_CACHE pointer
|
|
||||||
(when implemented) has to be present and updated in every binary unit which
|
|
||||||
is not compiled statically into PHP. So any DLL, DSO, EXE, etc. has to take
|
|
||||||
care about defining and updating it's TSRMLS cache. An update should happen
|
|
||||||
before any globals was accessed.
|
|
||||||
|
|
||||||
Porting an extension or SAPI is usually as easy as removing all the TSRMLS_*
|
|
||||||
occurrences and integrating the macros mentioned above. However if tsrm_ls
|
|
||||||
is used explicitly, its usage can be considered obsolete in most cases.
|
|
||||||
Additionally, if an extension triggers its own threads, TSRMLS_CACHE shouldn't
|
|
||||||
be passed to that threads directly.
|
|
||||||
|
|
||||||
When working with CTOR/DTOR for the extension globals, only the data passed
|
|
||||||
as parameters should be touched. For example, don't use code like
|
|
||||||
free(MYEXT_G(vars)); inside globals destructor, as it possibly can destroy
|
|
||||||
the data from a wrong thread. Instead use the pointer to the data delivered
|
|
||||||
into the destructor. So the previous example could look like
|
|
||||||
free(my_struct->vars); given the income was casted to (struct my_struct *).
|
|
||||||
|
|
||||||
A new macro was introduced to simplify the declaration to the extension
|
|
||||||
globals. A simplified declaration looks as follows
|
|
||||||
|
|
||||||
#define MYEXT_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(myext, v)
|
|
||||||
|
|
||||||
Another new macro ZEND_MODULE_GLOBALS_BULK(myext) delivers the corresponding
|
|
||||||
globals struct as a whole.
|
|
||||||
|
|
||||||
Two new storage specifiers was introduced.
|
|
||||||
|
|
||||||
ZEND_EXT_TLS - expand to an appropriate thread specific storage specifier in
|
|
||||||
the thread safe build, expands to empty in a non thread safe
|
|
||||||
build.
|
|
||||||
ZEND_TLS - expands to an appropriate thread specific storage specifier
|
|
||||||
with static visibility in the thread safe build, expands to
|
|
||||||
static specifier in a non thread safe build.
|
|
||||||
|
|
||||||
Variables declared with these storage specifiers can not be shared across
|
|
||||||
threads. While ZEND_TLS enforces the local scope visibility, ZEND_EXT_TLS
|
|
||||||
pertains to the visiblity across several compilation units. In both cases,
|
|
||||||
there's no portable way to achieve the visibility across shared objects.
|
|
||||||
Thus, these specifiers are not compatible with ZEND_API and PHPAPI specifiers.
|
|
||||||
|
|
||||||
q. gc_collect_cycles() is now a function pointer, and can be replaced in the
|
|
||||||
same manner as zend_execute_ex() if needed (for example, to include the
|
|
||||||
time spent in the garbage collector in a profiler). The default
|
|
||||||
implementation has been renamed to zend_gc_collect_cycles(), and is
|
|
||||||
exported with ZEND_API.
|
|
||||||
|
|
||||||
r. In accordance with general use of size_t as string length, all PDO API
|
|
||||||
functions now use size_t for string length.
|
|
||||||
|
|
||||||
s. Removed ZEND_REGISTER/FETCH_RESOURCE, use zend_fetch_resource and
|
|
||||||
and zend_register_resource instead, zend_fetch_resource accepts a zend_resource *
|
|
||||||
as first argument, if you still need to fetch a resource from zval, use
|
|
||||||
zend_fetch_resource_ex. More details can be found in Zend/zend_list.c.
|
|
||||||
|
|
||||||
t. Optimized strings concatenation.
|
|
||||||
ZEND_ADD_STRING/VAR/CHAR are replaced with ZEND_ROPE_INIT, ZEND_ROPE_ADD,
|
|
||||||
ZEND_ROPE_END.
|
|
||||||
Instead of reallocation and copying string on each ZEND_ADD_STRING/VAR/CAHR,
|
|
||||||
collect all the strings and then allocate and construct the resulting string once.
|
|
||||||
|
|
||||||
u. Streams changes
|
|
||||||
- It is possible to do blocking reads on Windows pipes. It can be done either
|
|
||||||
using context stream option PHP_STREAM_OPTION_PIPE_BLOCKING or
|
|
||||||
adding STREAM_USE_BLOCKING_PIPE when opening the stream.
|
|
||||||
|
|
||||||
v. Sort algorithm changes
|
|
||||||
- Improved zend_qsort(using hybrid sorting algo) for better performance,
|
|
||||||
and also renamed zend_qsort to zend_sort.
|
|
||||||
- Added stable sorting algo zend_insert_sort.
|
|
||||||
|
|
||||||
w. Tick functions internal API change
|
|
||||||
Tick functions have different declaration now. They expect a single
|
|
||||||
parameter while before they were parameterless. When registering the
|
|
||||||
tick function a value for this parameter must be passed. This value will be
|
|
||||||
provided to the tick function on every execution.
|
|
||||||
|
|
||||||
========================
|
========================
|
||||||
2. Build system changes
|
2. Build system changes
|
||||||
========================
|
========================
|
||||||
|
@ -260,65 +29,7 @@ changes. See: https://wiki.php.net/phpng-upgrading
|
||||||
|
|
||||||
b. Windows build system changes
|
b. Windows build system changes
|
||||||
|
|
||||||
- Besides Visual Studio, building with Clang or Intel Composer is now
|
|
||||||
possible. To enable an alternative toolset, add the option
|
|
||||||
--with-toolset=[vs,clang,icc] to the configure line. The default
|
|
||||||
toolset is vs. Still clang or icc need the correct environment
|
|
||||||
which involves many tools from the vs toolset.
|
|
||||||
|
|
||||||
The toolset option is supported by phpize as well.
|
|
||||||
|
|
||||||
AWARENESS The only recommended and supported toolset to produce production
|
|
||||||
ready binaries is Visual Studio. Still other compilers can be used now for
|
|
||||||
testing and analyzing purposes.
|
|
||||||
|
|
||||||
- configure.js now produces response files which are passed to the linker
|
|
||||||
and library manager. This solves the issues with the long command lines
|
|
||||||
which can exceed the OS limit.
|
|
||||||
|
|
||||||
- with clang toolset, an option --with-uncritical-warn-choke is available,
|
|
||||||
which suppresses the most frequent false positive warnings
|
|
||||||
|
|
||||||
- the --with-mp option will by default utilize all the available cores. It's
|
|
||||||
enabled by default for release builds and can be disabled with the special
|
|
||||||
"disable" keyword.
|
|
||||||
|
|
||||||
========================
|
========================
|
||||||
3. Module changes
|
3. Module changes
|
||||||
========================
|
========================
|
||||||
|
|
||||||
Session:
|
|
||||||
|
|
||||||
- PS_MOD_UPDATE_TIMESTAMP() session save handler definition is added. New
|
|
||||||
save handler should use PS_MOD_UPDATE_TIMESTAMP() definition. Save handler
|
|
||||||
must not refer/change PS() variables directly from save handler. Use
|
|
||||||
parameters.
|
|
||||||
- PS_MOD()/PS_MOD_SID() macro exist only for transition. Beware these
|
|
||||||
save handlers are less secure and slower than PS_MOD_UPDATE_TIMESTAMP().
|
|
||||||
- PS(invalid_session_id) was removed. It was never worked as it supposed.
|
|
||||||
To report invalid session ID, use PS_VALIDATE_SID() handler.
|
|
||||||
- PS_VALIDATE_SID() defines session ID validation handler. This handler
|
|
||||||
must validate if requested session ID exists in session data storage or not.
|
|
||||||
Do not access PS(id) directly, but use this handler and it's parameter.
|
|
||||||
- PS_UPDATE_TIMESTAMP() defines timestamp updating handler. This handler
|
|
||||||
must update session data timestamp for GC if it is needed. e.g. Memcache
|
|
||||||
updates timestamp on read, so it does not need to update timestamp. Return
|
|
||||||
SUCCESS simply for this case.
|
|
||||||
- PS_CREATE_SID() should check session ID collision. Return NULL for failure.
|
|
||||||
- More documentation can be found in ext/session/mod_files.c as comments.
|
|
||||||
mod_files.c may be used as reference implementation.
|
|
||||||
|
|
||||||
Openssl:
|
|
||||||
- several ext/openssl functions require the inclusion of the applink shim
|
|
||||||
as documented in the OpenSSL FAQ https://www.openssl.org/support/faq.html#PROG2
|
|
||||||
to properly work on Windows. While this primarily affects the OpenSSL
|
|
||||||
functionality, the shim needs to be included into the executable file
|
|
||||||
which loads the extension DLL, not into the extension DLL itself. Alternatively
|
|
||||||
it can be compiled and linked with the main program as a separate object file.
|
|
||||||
More information and explanation in the linked OpenSSL FAQ.
|
|
||||||
|
|
||||||
Thus, this primarily affects any WAMP or other redistributions bundling the
|
|
||||||
official PHP release zipballs or building from sources. The applink shim is
|
|
||||||
already integrated with all the PHP executables from the official distribution
|
|
||||||
starting with 7.0.0beta1.
|
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,20 @@ function test3($a, $b) {
|
||||||
|
|
||||||
test1();
|
test1();
|
||||||
test2(1);
|
test2(1);
|
||||||
test2();
|
try {
|
||||||
|
test2();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
test3(1,2);
|
test3(1,2);
|
||||||
|
|
||||||
call_user_func("test1");
|
call_user_func("test1");
|
||||||
call_user_func("test3", 1);
|
try {
|
||||||
|
call_user_func("test3", 1);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
call_user_func("test3", 1, 2);
|
call_user_func("test3", 1, 2);
|
||||||
|
|
||||||
class test {
|
class test {
|
||||||
|
@ -38,14 +47,10 @@ echo "Done\n";
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
int(0)
|
int(0)
|
||||||
int(1)
|
int(1)
|
||||||
|
Exception: Too few arguments to function test2(), 0 passed in %s001.php on line 18 and exactly 1 expected
|
||||||
Warning: Missing argument 1 for test2(), called in %s on line %d
|
|
||||||
int(0)
|
|
||||||
int(2)
|
int(2)
|
||||||
int(0)
|
int(0)
|
||||||
|
Exception: Too few arguments to function test3(), 1 passed in %s001.php on line 27 and exactly 2 expected
|
||||||
Warning: Missing argument 2 for test3()%s
|
|
||||||
int(1)
|
|
||||||
int(2)
|
int(2)
|
||||||
int(1)
|
int(1)
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,19 @@ function test3($a, $b) {
|
||||||
test1();
|
test1();
|
||||||
test1(10);
|
test1(10);
|
||||||
test2(1);
|
test2(1);
|
||||||
test2();
|
try {
|
||||||
|
test2();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
test3(1,2);
|
test3(1,2);
|
||||||
|
|
||||||
call_user_func("test1");
|
call_user_func("test1");
|
||||||
call_user_func("test3", 1);
|
try {
|
||||||
|
call_user_func("test3", 1);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
call_user_func("test3", 1, 2);
|
call_user_func("test3", 1, 2);
|
||||||
|
|
||||||
class test {
|
class test {
|
||||||
|
@ -62,14 +70,7 @@ int(1)
|
||||||
|
|
||||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||||
bool(false)
|
bool(false)
|
||||||
|
Exception: Too few arguments to function test2(), 0 passed in %s002.php on line %d and exactly 1 expected
|
||||||
Warning: Missing argument 1 for test2(), called in %s on line %d and defined in %s on line %d
|
|
||||||
|
|
||||||
Warning: func_get_arg(): Argument 0 not passed to function in %s on line %d
|
|
||||||
bool(false)
|
|
||||||
|
|
||||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
|
||||||
bool(false)
|
|
||||||
int(1)
|
int(1)
|
||||||
int(2)
|
int(2)
|
||||||
|
|
||||||
|
@ -84,15 +85,7 @@ bool(false)
|
||||||
|
|
||||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
||||||
bool(false)
|
bool(false)
|
||||||
|
Exception: Too few arguments to function test3(), 1 passed in %s002.php on line %d and exactly 2 expected
|
||||||
Warning: Missing argument 2 for test3()%s
|
|
||||||
int(1)
|
|
||||||
|
|
||||||
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
|
|
||||||
bool(false)
|
|
||||||
|
|
||||||
Warning: func_get_arg(): Argument 2 not passed to function in %s on line %d
|
|
||||||
bool(false)
|
|
||||||
int(1)
|
int(1)
|
||||||
int(2)
|
int(2)
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,19 @@ function test3($a, $b) {
|
||||||
test1();
|
test1();
|
||||||
test1(10);
|
test1(10);
|
||||||
test2(1);
|
test2(1);
|
||||||
test2();
|
try {
|
||||||
|
test2();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
test3(1,2);
|
test3(1,2);
|
||||||
|
|
||||||
call_user_func("test1");
|
call_user_func("test1");
|
||||||
call_user_func("test3", 1);
|
try {
|
||||||
|
call_user_func("test3", 1);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
call_user_func("test3", 1, 2);
|
call_user_func("test3", 1, 2);
|
||||||
|
|
||||||
class test {
|
class test {
|
||||||
|
@ -47,10 +55,7 @@ array(1) {
|
||||||
[0]=>
|
[0]=>
|
||||||
int(1)
|
int(1)
|
||||||
}
|
}
|
||||||
|
Exception: Too few arguments to function test2(), 0 passed in %s003.php on line %d and exactly 1 expected
|
||||||
Warning: Missing argument 1 for test2(), called in %s on line %d and defined in %s on line %d
|
|
||||||
array(0) {
|
|
||||||
}
|
|
||||||
array(2) {
|
array(2) {
|
||||||
[0]=>
|
[0]=>
|
||||||
int(1)
|
int(1)
|
||||||
|
@ -59,12 +64,7 @@ array(2) {
|
||||||
}
|
}
|
||||||
array(0) {
|
array(0) {
|
||||||
}
|
}
|
||||||
|
Exception: Too few arguments to function test3(), 1 passed in %s003.php on line %d and exactly 2 expected
|
||||||
Warning: Missing argument 2 for test3()%s
|
|
||||||
array(1) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
}
|
|
||||||
array(2) {
|
array(2) {
|
||||||
[0]=>
|
[0]=>
|
||||||
int(1)
|
int(1)
|
||||||
|
|
|
@ -31,40 +31,4 @@ $test->bar();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
object(Exception)#%d (7) {
|
Fatal error: Cannot re-assign $this in %s030.php on line 11
|
||||||
["message":protected]=>
|
|
||||||
string(3) "foo"
|
|
||||||
["string":"Exception":private]=>
|
|
||||||
string(0) ""
|
|
||||||
["code":protected]=>
|
|
||||||
int(0)
|
|
||||||
["file":protected]=>
|
|
||||||
string(%d) "%s030.php"
|
|
||||||
["line":protected]=>
|
|
||||||
int(%d)
|
|
||||||
["trace":"Exception":private]=>
|
|
||||||
array(1) {
|
|
||||||
[0]=>
|
|
||||||
array(6) {
|
|
||||||
["file"]=>
|
|
||||||
string(%d) "%s030.php"
|
|
||||||
["line"]=>
|
|
||||||
int(%d)
|
|
||||||
["function"]=>
|
|
||||||
string(3) "bar"
|
|
||||||
["class"]=>
|
|
||||||
string(3) "foo"
|
|
||||||
["type"]=>
|
|
||||||
string(2) "->"
|
|
||||||
["args"]=>
|
|
||||||
array(0) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
["previous":"Exception":private]=>
|
|
||||||
NULL
|
|
||||||
}
|
|
||||||
'test' => '0'
|
|
||||||
'test_2' => '1'
|
|
||||||
'test_3' => '2'
|
|
||||||
ok
|
|
||||||
|
|
|
@ -38,11 +38,19 @@ var_dump($c);
|
||||||
echo "Done\n";
|
echo "Done\n";
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
|
|
||||||
|
Warning: A non-numeric value encountered in %s on line %d
|
||||||
int(75636)
|
int(75636)
|
||||||
|
|
||||||
|
Notice: A non well formed numeric value encountered in %s on line %d
|
||||||
int(951858)
|
int(951858)
|
||||||
int(48550510)
|
int(48550510)
|
||||||
float(75661.68)
|
float(75661.68)
|
||||||
|
|
||||||
|
Warning: A non-numeric value encountered in %s on line %d
|
||||||
int(75636)
|
int(75636)
|
||||||
|
|
||||||
|
Notice: A non well formed numeric value encountered in %s on line %d
|
||||||
int(951858)
|
int(951858)
|
||||||
int(48550510)
|
int(48550510)
|
||||||
float(75661.68)
|
float(75661.68)
|
||||||
|
|
|
@ -19,8 +19,13 @@ var_dump($c);
|
||||||
echo "Done\n";
|
echo "Done\n";
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
|
|
||||||
|
Warning: A non-numeric value encountered in %s on line %d
|
||||||
|
|
||||||
Exception: Unsupported operand types
|
Exception: Unsupported operand types
|
||||||
|
|
||||||
|
Warning: A non-numeric value encountered in %s on line %d
|
||||||
|
|
||||||
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
|
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 {main}
|
#0 {main}
|
||||||
|
|
15
Zend/tests/anon/013.phpt
Normal file
15
Zend/tests/anon/013.phpt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
--TEST--
|
||||||
|
closure binding to anonymous class
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$class = new class {};
|
||||||
|
$foo = function() {
|
||||||
|
return $this;
|
||||||
|
};
|
||||||
|
|
||||||
|
$closure = Closure::bind($foo, $class, $class);
|
||||||
|
var_dump($closure());
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
object(class@anonymous)#1 (0) {
|
||||||
|
}
|
16
Zend/tests/anon/014.phpt
Normal file
16
Zend/tests/anon/014.phpt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
--TEST--
|
||||||
|
anonymous class trait binding
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
trait TaskTrait {
|
||||||
|
function run() {
|
||||||
|
return 'Running...';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$class = new class() {
|
||||||
|
use TaskTrait;
|
||||||
|
};
|
||||||
|
var_dump($class->run());
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
string(10) "Running..."
|
|
@ -154,7 +154,7 @@ Warning: assert(): assert(0 && ($a = function () {
|
||||||
$x = $a ? $b : $c;
|
$x = $a ? $b : $c;
|
||||||
$x = $a ?: $c;
|
$x = $a ?: $c;
|
||||||
$x = $a ?? $b;
|
$x = $a ?? $b;
|
||||||
list($a, $b, $c) = [1, 2 => 'x', 'z' => 'c'];
|
[$a, $b, $c] = [1, 2 => 'x', 'z' => 'c'];
|
||||||
@foo();
|
@foo();
|
||||||
$y = clone $x;
|
$y = clone $x;
|
||||||
yield 1 => 2;
|
yield 1 => 2;
|
||||||
|
|
19
Zend/tests/assert/indirect_var_access_misoptimization.phpt
Normal file
19
Zend/tests/assert/indirect_var_access_misoptimization.phpt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
--TEST--
|
||||||
|
Misoptimization when variable is modified by assert()
|
||||||
|
--INI--
|
||||||
|
zend.assertions=1
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
$i = 0;
|
||||||
|
assert('$i = new stdClass');
|
||||||
|
$i += 1;
|
||||||
|
var_dump($i);
|
||||||
|
}
|
||||||
|
test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Notice: Object of class stdClass could not be converted to int in %s on line %d
|
||||||
|
int(2)
|
|
@ -6,9 +6,16 @@ $a = new stdClass();
|
||||||
$x = "";
|
$x = "";
|
||||||
$a->$x = "string('')";
|
$a->$x = "string('')";
|
||||||
var_dump($a);
|
var_dump($a);
|
||||||
|
$a->{"\0"} = 42;
|
||||||
|
var_dump($a);
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Cannot access empty property in %sbug29015.php:4
|
object(stdClass)#1 (1) {
|
||||||
|
[""]=>
|
||||||
|
string(10) "string('')"
|
||||||
|
}
|
||||||
|
|
||||||
|
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 {main}
|
#0 {main}
|
||||||
thrown in %sbug29015.php on line 4
|
thrown in %s on line %d
|
||||||
|
|
|
@ -3,7 +3,7 @@ Bug #29883 (isset gives invalid values on strings)
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
$x = "bug";
|
$x = "bug";
|
||||||
var_dump(isset($x[-1]));
|
var_dump(isset($x[-10]));
|
||||||
var_dump(isset($x["1"]));
|
var_dump(isset($x["1"]));
|
||||||
echo $x["1"]."\n";
|
echo $x["1"]."\n";
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -18,7 +18,7 @@ var_dump(isset($a['b']));
|
||||||
$simpleString = "Bogus String Text";
|
$simpleString = "Bogus String Text";
|
||||||
echo isset($simpleString->wrong)?"bug\n":"ok\n";
|
echo isset($simpleString->wrong)?"bug\n":"ok\n";
|
||||||
echo isset($simpleString["wrong"])?"bug\n":"ok\n";
|
echo isset($simpleString["wrong"])?"bug\n":"ok\n";
|
||||||
echo isset($simpleString[-1])?"bug\n":"ok\n";
|
echo isset($simpleString[-20])?"bug\n":"ok\n";
|
||||||
echo isset($simpleString[0])?"ok\n":"bug\n";
|
echo isset($simpleString[0])?"ok\n":"bug\n";
|
||||||
echo isset($simpleString["0"])?"ok\n":"bug\n";
|
echo isset($simpleString["0"])?"ok\n":"bug\n";
|
||||||
echo isset($simpleString["16"])?"ok\n":"bug\n";
|
echo isset($simpleString["16"])?"ok\n":"bug\n";
|
||||||
|
|
|
@ -19,15 +19,19 @@ function NormalTest($a)
|
||||||
echo "Hi!";
|
echo "Hi!";
|
||||||
}
|
}
|
||||||
|
|
||||||
NormalTest();
|
try {
|
||||||
FooTest();
|
NormalTest();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FooTest();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
FooTest(new Foo());
|
FooTest(new Foo());
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Warning: Missing argument 1 for NormalTest(), called in %sbug33996.php on line %d and defined in %sbug33996.php on line %d
|
Exception: Too few arguments to function NormalTest(), 0 passed in %sbug33996.php on line 18 and exactly 1 expected
|
||||||
Hi!
|
Exception: Too few arguments to function FooTest(), 0 passed in %sbug33996.php on line 23 and exactly 1 expected
|
||||||
Fatal error: Uncaught TypeError: Argument 1 passed to FooTest() must be an instance of Foo, none given, called in %sbug33996.php on line %d and defined in %sbug33996.php:%d
|
Hello!
|
||||||
Stack trace:
|
|
||||||
#0 %s(%d): FooTest()
|
|
||||||
#1 {main}
|
|
||||||
thrown in %sbug33996.php on line %d
|
|
||||||
|
|
|
@ -43,7 +43,9 @@ Non-static method A::A_ftk() should not be called statically
|
||||||
1 %sbug38047.php:13 get_error_context()
|
1 %sbug38047.php:13 get_error_context()
|
||||||
2 %sbug38047.php:36 kalus_error_handler()
|
2 %sbug38047.php:36 kalus_error_handler()
|
||||||
|
|
||||||
Missing argument 1 for A::A_ftk(), called in %sbug38047.php on line 36 and defined
|
|
||||||
1 %sbug38047.php:13 get_error_context()
|
Fatal error: Uncaught Error: Too few arguments to function A::A_ftk(), 0 passed in %sbug38047.php on line 36 and exactly 1 expected in %sbug38047.php:7
|
||||||
2 %sbug38047.php:7 kalus_error_handler()
|
Stack trace:
|
||||||
3 %sbug38047.php:36 A_ftk()
|
#0 %sbug38047.php(36): A::A_ftk()
|
||||||
|
#1 {main}
|
||||||
|
thrown in %sbug38047.php on line 7
|
||||||
|
|
|
@ -9,7 +9,7 @@ $foo[0]->bar = "xyz";
|
||||||
echo "Done\n";
|
echo "Done\n";
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Cannot use string offset as an array in %s:%d
|
Fatal error: Uncaught Error: Cannot use string offset as an object in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 {main}
|
#0 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
|
@ -7,7 +7,7 @@ $b = &$a[1];
|
||||||
$b = "f";
|
$b = "f";
|
||||||
echo $a;
|
echo $a;
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Cannot create references to/from string offsets nor overloaded objects in %sbug49866.php:3
|
Fatal error: Uncaught Error: Cannot create references to/from string offsets in %sbug49866.php:3
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 {main}
|
#0 {main}
|
||||||
thrown in %sbug49866.php on line 3
|
thrown in %sbug49866.php on line 3
|
||||||
|
|
|
@ -10,14 +10,14 @@ class A {
|
||||||
}
|
}
|
||||||
|
|
||||||
$a = new A();
|
$a = new A();
|
||||||
$prop = null;
|
$prop = "\0";
|
||||||
|
|
||||||
unset($a->$prop);
|
unset($a->$prop);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Cannot access empty property in %s:%d
|
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 %s(%d): A->__unset('')
|
#0 %s(%d): A->__unset('\x00')
|
||||||
#1 {main}
|
#1 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
|
@ -10,14 +10,14 @@ class A {
|
||||||
}
|
}
|
||||||
|
|
||||||
$a = new A();
|
$a = new A();
|
||||||
$prop = null;
|
$prop = "\0";
|
||||||
|
|
||||||
$a->$prop = 2;
|
$a->$prop = 2;
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Cannot access empty property in %s:%d
|
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 %s(%d): A->__set('', 2)
|
#0 %s(%d): A->__set('\x00', 2)
|
||||||
#1 {main}
|
#1 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
|
@ -10,14 +10,14 @@ class A {
|
||||||
}
|
}
|
||||||
|
|
||||||
$a = new A();
|
$a = new A();
|
||||||
$prop = null;
|
$prop = "\0";
|
||||||
|
|
||||||
var_dump($a->$prop);
|
var_dump($a->$prop);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Cannot access empty property in %s:%d
|
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 %s(%d): A->__get('')
|
#0 %s(%d): A->__get('\x00')
|
||||||
#1 {main}
|
#1 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
|
@ -8,7 +8,7 @@ class MyClass {
|
||||||
$this->myRef = $value;
|
$this->myRef = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$myGlobal=new MyClass($myGlobal);
|
$myGlobal=new MyClass();
|
||||||
$myGlobal->myRef=&$myGlobal;
|
$myGlobal->myRef=&$myGlobal;
|
||||||
$myGlobal->myNonExistentProperty="ok\n";
|
$myGlobal->myNonExistentProperty="ok\n";
|
||||||
echo $myGlobal;
|
echo $myGlobal;
|
||||||
|
|
65
Zend/tests/bug53432.phpt
Normal file
65
Zend/tests/bug53432.phpt
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #53432: Assignment via string index access on an empty string converts to array
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$str = '';
|
||||||
|
var_dump($str[0] = 'a');
|
||||||
|
var_dump($str);
|
||||||
|
|
||||||
|
$str = '';
|
||||||
|
var_dump($str[5] = 'a');
|
||||||
|
var_dump($str);
|
||||||
|
|
||||||
|
$str = '';
|
||||||
|
var_dump($str[-1] = 'a');
|
||||||
|
var_dump($str);
|
||||||
|
|
||||||
|
$str = '';
|
||||||
|
var_dump($str['foo'] = 'a');
|
||||||
|
var_dump($str);
|
||||||
|
|
||||||
|
$str = '';
|
||||||
|
try {
|
||||||
|
var_dump($str[] = 'a');
|
||||||
|
} catch (Error $e) {
|
||||||
|
echo "Error: {$e->getMessage()}\n";
|
||||||
|
}
|
||||||
|
var_dump($str);
|
||||||
|
|
||||||
|
$str = '';
|
||||||
|
try {
|
||||||
|
var_dump($str[0] += 1);
|
||||||
|
} catch (Error $e) {
|
||||||
|
echo "Error: {$e->getMessage()}\n";
|
||||||
|
}
|
||||||
|
var_dump($str);
|
||||||
|
|
||||||
|
$str = '';
|
||||||
|
try {
|
||||||
|
var_dump($str[0][0] = 'a');
|
||||||
|
} catch (Error $e) {
|
||||||
|
echo "Error: {$e->getMessage()}\n";
|
||||||
|
}
|
||||||
|
var_dump($str);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
string(1) "a"
|
||||||
|
string(1) "a"
|
||||||
|
string(1) "a"
|
||||||
|
string(6) " a"
|
||||||
|
|
||||||
|
Warning: Illegal string offset: -1 in %s on line %d
|
||||||
|
NULL
|
||||||
|
string(0) ""
|
||||||
|
|
||||||
|
Warning: Illegal string offset 'foo' in %s on line %d
|
||||||
|
string(1) "a"
|
||||||
|
string(1) "a"
|
||||||
|
Error: [] operator not supported for strings
|
||||||
|
string(0) ""
|
||||||
|
Error: Cannot use assign-op operators with string offsets
|
||||||
|
string(0) ""
|
||||||
|
Error: Cannot use string offset as an array
|
||||||
|
string(0) ""
|
|
@ -6,7 +6,7 @@ function f(callable $c) {}
|
||||||
f();
|
f();
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught TypeError: Argument 1 passed to f() must be callable, none given, called in %s on line 3 and defined in %s:%d
|
Fatal error: Uncaught Error: Too few arguments to function f(), 0 passed in %s on line 3 and exactly 1 expected in %s:2
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 %s(%d): f()
|
#0 %s(%d): f()
|
||||||
#1 {main}
|
#1 {main}
|
||||||
|
|
20
Zend/tests/bug62814.phpt
Normal file
20
Zend/tests/bug62814.phpt
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #62814: It is possible to stiffen child class members visibility
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class A {
|
||||||
|
private function test() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class B extends A {
|
||||||
|
protected function test() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class C extends B {
|
||||||
|
private function test() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Access level to C::test() must be protected (as in class B) or weaker in %s on line %d
|
|
@ -57,8 +57,13 @@ $bar = foo3();
|
||||||
string(9) "not catch"
|
string(9) "not catch"
|
||||||
NULL
|
NULL
|
||||||
|
|
||||||
Fatal error: Uncaught Error: Class 'NotExists' not found in %sbug65784.php:%d
|
Fatal error: Uncaught Exception: not catched in %sbug65784.php:42
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 %s(%d): foo3()
|
#0 %sbug65784.php(52): foo3()
|
||||||
#1 {main}
|
#1 {main}
|
||||||
thrown in %sbug65784.php on line %d
|
|
||||||
|
Next Error: Class 'NotExists' not found in %sbug65784.php:46
|
||||||
|
Stack trace:
|
||||||
|
#0 %sbug65784.php(52): foo3()
|
||||||
|
#1 {main}
|
||||||
|
thrown in %sbug65784.php on line 46
|
||||||
|
|
|
@ -13,6 +13,4 @@ $x = $c->test();
|
||||||
print_r($x);
|
print_r($x);
|
||||||
unset($c, $x);
|
unset($c, $x);
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Array
|
Fatal error: Cannot unset $this in %sbug68370.php on line 4
|
||||||
(
|
|
||||||
)
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ class Bar {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
|
if (!isset(self::$instance)) return;
|
||||||
Foo::getInstance();
|
Foo::getInstance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
42
Zend/tests/bug69989_2.phpt
Normal file
42
Zend/tests/bug69989_2.phpt
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
--TEST--
|
||||||
|
Collection of some cycles on unfinished generators
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// CV
|
||||||
|
function gen1() {
|
||||||
|
$gen = yield;
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
|
||||||
|
$gen = gen1();
|
||||||
|
$gen->send($gen);
|
||||||
|
|
||||||
|
// This
|
||||||
|
class Test {
|
||||||
|
public $gen;
|
||||||
|
public function gen2() {
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$test = new Test;
|
||||||
|
$test->gen = $test->gen2();
|
||||||
|
|
||||||
|
// Closure object
|
||||||
|
$gen3 = (function() use (&$gen3) {
|
||||||
|
yield;
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Yield from array
|
||||||
|
function gen4() {
|
||||||
|
yield from [yield];
|
||||||
|
}
|
||||||
|
|
||||||
|
$gen = gen4();
|
||||||
|
$gen->send($gen);
|
||||||
|
|
||||||
|
?>
|
||||||
|
===DONE===
|
||||||
|
--EXPECT--
|
||||||
|
===DONE===
|
44
Zend/tests/bug69989_3.phpt
Normal file
44
Zend/tests/bug69989_3.phpt
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
--TEST--
|
||||||
|
Generator cycle collection edge cases
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Extra args
|
||||||
|
function gen1() {
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
$obj = new stdClass;
|
||||||
|
$obj->gen = gen1($obj);
|
||||||
|
|
||||||
|
// Symtable
|
||||||
|
function gen2() {
|
||||||
|
$varName = 'a';
|
||||||
|
$$varName = yield;
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
$gen = gen2();
|
||||||
|
$gen->send($gen);
|
||||||
|
|
||||||
|
// Symtable indirect
|
||||||
|
function gen3() {
|
||||||
|
$varName = 'a';
|
||||||
|
$$varName = 42;
|
||||||
|
$var = yield;
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
$gen = gen3();
|
||||||
|
$gen->send($gen);
|
||||||
|
|
||||||
|
// Yield from root
|
||||||
|
function gen4() {
|
||||||
|
yield from yield;
|
||||||
|
}
|
||||||
|
$gen = gen4();
|
||||||
|
$gen2 = gen4($gen);
|
||||||
|
$gen2->send([1, 2, 3]);
|
||||||
|
$gen->send($gen2);
|
||||||
|
|
||||||
|
?>
|
||||||
|
===DONE===
|
||||||
|
--EXPECT--
|
||||||
|
===DONE===
|
|
@ -34,4 +34,4 @@ try {
|
||||||
string(36) "Cannot use string offset as an array"
|
string(36) "Cannot use string offset as an array"
|
||||||
string(27) "Cannot unset string offsets"
|
string(27) "Cannot unset string offsets"
|
||||||
string(41) "Only variables can be passed by reference"
|
string(41) "Only variables can be passed by reference"
|
||||||
string(64) "Cannot increment/decrement overloaded objects nor string offsets"
|
string(41) "Cannot increment/decrement string offsets"
|
||||||
|
|
|
@ -15,7 +15,7 @@ var_dump($c);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Warning: Cannot bind internal method SplDoublyLinkedList::count() to object of class cls in %s on line %d
|
Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls in %s on line %d
|
||||||
NULL
|
NULL
|
||||||
|
|
||||||
Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d
|
Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d
|
||||||
|
|
|
@ -19,4 +19,8 @@ try {
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Missing argument 1 for foo(), called in %sbug70689.php on line %d and defined
|
Fatal error: Uncaught Error: Too few arguments to function foo(), 0 passed in %sbug70689.php on line 12 and exactly 1 expected in %sbug70689.php:3
|
||||||
|
Stack trace:
|
||||||
|
#0 %sbug70689.php(12): foo()
|
||||||
|
#1 {main}
|
||||||
|
thrown in %sbug70689.php on line 3
|
||||||
|
|
47
Zend/tests/bug70918.phpt
Normal file
47
Zend/tests/bug70918.phpt
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #70918 (Segfault using static outside of class scope)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
try {
|
||||||
|
static::x;
|
||||||
|
} catch (Error $e) {
|
||||||
|
var_dump($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
parent::x;
|
||||||
|
} catch (Error $e) {
|
||||||
|
var_dump($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
self::x;
|
||||||
|
} catch (Error $e) {
|
||||||
|
var_dump($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new static;
|
||||||
|
} catch (Error $e) {
|
||||||
|
var_dump($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
static::x();
|
||||||
|
} catch (Error $e) {
|
||||||
|
var_dump($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
static::$i;
|
||||||
|
} catch (Error $e) {
|
||||||
|
var_dump($e->getMessage());
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(52) "Cannot access static:: when no class scope is active"
|
||||||
|
string(52) "Cannot access parent:: when no class scope is active"
|
||||||
|
string(50) "Cannot access self:: when no class scope is active"
|
||||||
|
string(52) "Cannot access static:: when no class scope is active"
|
||||||
|
string(52) "Cannot access static:: when no class scope is active"
|
||||||
|
string(52) "Cannot access static:: when no class scope is active"
|
13
Zend/tests/bug71196.phpt
Normal file
13
Zend/tests/bug71196.phpt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #71196 (Memory leak with out-of-order live ranges)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
try {
|
||||||
|
$a = "1";
|
||||||
|
[1, (y().$a.$a) . ($a.$a)];
|
||||||
|
} catch (Error $e) {
|
||||||
|
var_dump($e->getMessage());
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(30) "Call to undefined function y()"
|
22
Zend/tests/bug71266.phpt
Normal file
22
Zend/tests/bug71266.phpt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #71266 (Missing separation of properties HT in foreach etc)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$one = 1;
|
||||||
|
$two = 2;
|
||||||
|
$arr = ['foo' => $one, 'bar' => $two];
|
||||||
|
$obj = (object) $arr;
|
||||||
|
foreach ($obj as $val) {
|
||||||
|
var_dump($val);
|
||||||
|
$obj->bar = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
$arr = ['foo' => $one, 'bar' => $two];
|
||||||
|
$obj = (object) $arr;
|
||||||
|
next($obj);
|
||||||
|
var_dump(current($arr));
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
int(1)
|
||||||
|
int(42)
|
||||||
|
int(1)
|
|
@ -1,7 +1,5 @@
|
||||||
--TEST--
|
--TEST--
|
||||||
bug #71428.1: inheritance with null default values
|
bug #71428.1: inheritance with null default values
|
||||||
--XFAIL--
|
|
||||||
This is a BC break
|
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
class A {
|
class A {
|
||||||
|
@ -11,5 +9,5 @@ class B extends A {
|
||||||
public function m(array $a = []) {}
|
public function m(array $a = []) {}
|
||||||
}
|
}
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Warning: Declaration of B::m(array $a = Array) should be compatible with A::m(array $a = NULL) in %sbug71428.1.php on line 7
|
Warning: Declaration of B::m(array $a = Array) should be compatible with A::m(?array $a = NULL) in %sbug71428.1.php on line 7
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
--TEST--
|
--TEST--
|
||||||
bug #71428: Validation type inheritance with = NULL
|
bug #71428: Validation type inheritance with = NULL
|
||||||
--XFAIL--
|
|
||||||
This is a BC break
|
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
class A { }
|
class A { }
|
||||||
|
@ -9,5 +7,5 @@ class B { public function m(A $a = NULL, $n) { echo "B.m";} };
|
||||||
class C extends B { public function m(A $a , $n) { echo "C.m";} };
|
class C extends B { public function m(A $a , $n) { echo "C.m";} };
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Warning: Declaration of C::m(A $a, $n) should be compatible with B::m(A $a = NULL, $n) in %sbug71428.3.php on line 4
|
Warning: Declaration of C::m(A $a, $n) should be compatible with B::m(?A $a, $n) in %sbug71428.3.php on line 4
|
||||||
|
|
||||||
|
|
27
Zend/tests/bug71572.phpt
Normal file
27
Zend/tests/bug71572.phpt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #71572: String offset assignment from an empty string inserts null byte
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$str = "abc";
|
||||||
|
var_dump($str{0} = "");
|
||||||
|
var_dump($str{1} = "");
|
||||||
|
var_dump($str{3} = "");
|
||||||
|
var_dump($str{10} = "");
|
||||||
|
var_dump($str);
|
||||||
|
?>
|
||||||
|
==DONE==
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: Cannot assign an empty string to a string offset in %s on line %d
|
||||||
|
NULL
|
||||||
|
|
||||||
|
Warning: Cannot assign an empty string to a string offset in %s on line %d
|
||||||
|
NULL
|
||||||
|
|
||||||
|
Warning: Cannot assign an empty string to a string offset in %s on line %d
|
||||||
|
NULL
|
||||||
|
|
||||||
|
Warning: Cannot assign an empty string to a string offset in %s on line %d
|
||||||
|
NULL
|
||||||
|
string(3) "abc"
|
||||||
|
==DONE==
|
14
Zend/tests/bug72107.phpt
Normal file
14
Zend/tests/bug72107.phpt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72107: Segfault when using func_get_args as error handler
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
set_error_handler('func_get_args');
|
||||||
|
function test($a) {
|
||||||
|
echo $undef;
|
||||||
|
}
|
||||||
|
test(1);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: Cannot call func_get_args() dynamically in %s on line %d
|
||||||
|
|
||||||
|
Notice: Undefined variable: undef in %s on line %d
|
|
@ -14,5 +14,6 @@ class Hello implements Foo {
|
||||||
}
|
}
|
||||||
echo "OK\n";
|
echo "OK\n";
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECTF--
|
||||||
OK
|
Fatal error: Declaration of Hello::bar(array $baz = Array) must be compatible with Foo::bar(?array $baz = NULL) in %s on line %d
|
||||||
|
|
||||||
|
|
35
Zend/tests/bug72177.phpt
Normal file
35
Zend/tests/bug72177.phpt
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Child
|
||||||
|
{
|
||||||
|
protected $bar;
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
$this->bar = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Parnt
|
||||||
|
{
|
||||||
|
protected $child;
|
||||||
|
|
||||||
|
public function doSomething()
|
||||||
|
{
|
||||||
|
$this->child = new Child();
|
||||||
|
|
||||||
|
$prop = new \ReflectionProperty($this, 'child');
|
||||||
|
$prop->setAccessible(true);
|
||||||
|
$prop->setValue($this, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$p = new Parnt();
|
||||||
|
$p->doSomething();
|
||||||
|
|
||||||
|
echo "OK\n";
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
OK
|
34
Zend/tests/bug72177_2.phpt
Normal file
34
Zend/tests/bug72177_2.phpt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class Foo
|
||||||
|
{
|
||||||
|
private $bar = 'bar';
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
unset($this->bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Bar extends Foo
|
||||||
|
{
|
||||||
|
private $baz = 'baz';
|
||||||
|
private static $tab = 'tab';
|
||||||
|
|
||||||
|
public function __get(string $name)
|
||||||
|
{
|
||||||
|
var_dump($this->baz);
|
||||||
|
var_dump(self::$tab);
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = new ReflectionProperty(Foo::class, 'bar');
|
||||||
|
|
||||||
|
$r->setAccessible(true);
|
||||||
|
echo "OK\n";
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
OK
|
27
Zend/tests/bug72188.phpt
Normal file
27
Zend/tests/bug72188.phpt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72188 (Nested try/finally blocks losing return value)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
function test() {
|
||||||
|
try {
|
||||||
|
return 5;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
echo 1;
|
||||||
|
} finally {
|
||||||
|
echo 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$a = test();
|
||||||
|
if($a !== 5) {
|
||||||
|
echo "FAILED: expected 5, received ", var_export($a), PHP_EOL;
|
||||||
|
} else {
|
||||||
|
echo "Passed", PHP_EOL;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
12Passed
|
11
Zend/tests/bug72221.phpt
Normal file
11
Zend/tests/bug72221.phpt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72221 (Segmentation fault in stream_get_line / zend_memnstr_ex)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
$fp = fopen("php://memory", "r+");
|
||||||
|
fwrite($fp, str_repeat("baad", 1024*1024));
|
||||||
|
rewind($fp);
|
||||||
|
stream_get_line($fp, 1024*1024*2, "aaaa");
|
||||||
|
echo "Done\n";
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
18
Zend/tests/bug72335.phpt
Normal file
18
Zend/tests/bug72335.phpt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
--TEST--
|
||||||
|
Misoptimize due to type narrowing
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
$b = false;
|
||||||
|
$x = (1<<53)+1;
|
||||||
|
do {
|
||||||
|
$x = 1.0 * ($x - (1<<53));
|
||||||
|
} while ($b);
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
var_dump(test());
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
float(1)
|
20
Zend/tests/bug72373.phpt
Normal file
20
Zend/tests/bug72373.phpt
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72373: TypeError after Generator function w/declared return type finishes
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function foo() : Generator {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
yield 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (foo() as $bar) {
|
||||||
|
echo $bar . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
10
Zend/tests/bug72395.phpt
Normal file
10
Zend/tests/bug72395.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72395 (list() regression)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
list(,,$a,,$b,) = array(1, 2, 3, 4, 5, 6);
|
||||||
|
var_dump($a, $b);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
int(3)
|
||||||
|
int(5)
|
14
Zend/tests/bug72441.phpt
Normal file
14
Zend/tests/bug72441.phpt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
--TEST--
|
||||||
|
Bug #72441 (Segmentation fault: RFC list_keys)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$array = [];
|
||||||
|
|
||||||
|
list(
|
||||||
|
'' => $foo,
|
||||||
|
$bar
|
||||||
|
) = $array;
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Cannot mix keyed and unkeyed array entries in assignments in %sbug72441.php on line %d
|
|
@ -13,7 +13,11 @@ test(function() { return new stdclass; });
|
||||||
test(function() { });
|
test(function() { });
|
||||||
|
|
||||||
$a = function($x) use ($y) {};
|
$a = function($x) use ($y) {};
|
||||||
test($a);
|
try {
|
||||||
|
test($a);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
test(new stdclass);
|
test(new stdclass);
|
||||||
|
|
||||||
|
@ -24,9 +28,7 @@ object(stdClass)#%d (0) {
|
||||||
NULL
|
NULL
|
||||||
|
|
||||||
Notice: Undefined variable: y in %s on line %d
|
Notice: Undefined variable: y in %s on line %d
|
||||||
|
Exception: Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected
|
||||||
Warning: Missing argument 1 for {closure}(), called in %s on line %d and defined in %s on line %d
|
|
||||||
NULL
|
|
||||||
|
|
||||||
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of Closure, instance of stdClass given, called in %s on line %d and defined in %s:%d
|
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of Closure, instance of stdClass given, called in %s on line %d and defined in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
|
|
|
@ -184,7 +184,7 @@ bindTo(new ClsChild, Cls::class):
|
||||||
Success!
|
Success!
|
||||||
|
|
||||||
bindTo(new ClsUnrelated, Cls::class):
|
bindTo(new ClsUnrelated, Cls::class):
|
||||||
Success!
|
Cannot bind method Cls::method() to object of class ClsUnrelated
|
||||||
|
|
||||||
bindTo(new Cls, null):
|
bindTo(new Cls, null):
|
||||||
Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
|
Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
|
||||||
|
@ -205,7 +205,7 @@ bindTo(new SplStack, SplDoublyLinkedList::class):
|
||||||
Success!
|
Success!
|
||||||
|
|
||||||
bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
|
bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
|
||||||
Cannot bind internal method SplDoublyLinkedList::count() to object of class ClsUnrelated
|
Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated
|
||||||
|
|
||||||
bindTo(null, null):
|
bindTo(null, null):
|
||||||
Cannot unbind $this of internal method
|
Cannot unbind $this of internal method
|
||||||
|
|
16
Zend/tests/closure_use_auto_global.phpt
Normal file
16
Zend/tests/closure_use_auto_global.phpt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
--TEST--
|
||||||
|
Cannot use() auto-global
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
$fn = function() use($GLOBALS) {
|
||||||
|
var_dump($GLOBALS);
|
||||||
|
};
|
||||||
|
$fn();
|
||||||
|
}
|
||||||
|
test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Cannot use auto-global as lexical variable in %s on line %d
|
14
Zend/tests/closure_use_parameter_name.phpt
Normal file
14
Zend/tests/closure_use_parameter_name.phpt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
--TEST--
|
||||||
|
Can't use name of lexical variable for parameter
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$a = 1;
|
||||||
|
$fn = function ($a) use ($a) {
|
||||||
|
var_dump($a);
|
||||||
|
};
|
||||||
|
$fn(2);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Cannot use lexical variable $a as a parameter name in %s on line %d
|
15
Zend/tests/closure_use_variable_twice.phpt
Normal file
15
Zend/tests/closure_use_variable_twice.phpt
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
--TEST--
|
||||||
|
Closure cannot use one variable twice
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$a = 1;
|
||||||
|
$fn = function() use ($a, &$a) {
|
||||||
|
$a = 2;
|
||||||
|
};
|
||||||
|
$fn();
|
||||||
|
var_dump($a);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Cannot use variable $a twice in %s on line %d
|
|
@ -44,7 +44,9 @@ var_dump(
|
||||||
);
|
);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECTF--
|
||||||
|
|
||||||
|
Warning: A non-numeric value encountered in %s on line %d
|
||||||
int(3)
|
int(3)
|
||||||
string(4) "1foo"
|
string(4) "1foo"
|
||||||
bool(false)
|
bool(false)
|
||||||
|
|
|
@ -9,7 +9,7 @@ class A {
|
||||||
var_dump(A::FOO);
|
var_dump(A::FOO);
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::FOO' in %s:%d
|
Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::BAR' in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 {main}
|
#0 {main}
|
||||||
thrown in %s on line %d
|
thrown in %s on line %d
|
||||||
|
|
29
Zend/tests/dynamic_call_005.phpt
Normal file
29
Zend/tests/dynamic_call_005.phpt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
--TEST--
|
||||||
|
Dynamic calls to scope introspection functions are forbidden
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test_calls($func) {
|
||||||
|
$i = 1;
|
||||||
|
|
||||||
|
array_map($func, [['i' => new stdClass]]);
|
||||||
|
var_dump($i);
|
||||||
|
|
||||||
|
$func(['i' => new stdClass]);
|
||||||
|
var_dump($i);
|
||||||
|
|
||||||
|
call_user_func($func, ['i' => new stdClass]);
|
||||||
|
var_dump($i);
|
||||||
|
}
|
||||||
|
test_calls('extract');
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: Cannot call extract() dynamically in %s on line %d
|
||||||
|
int(1)
|
||||||
|
|
||||||
|
Warning: Cannot call extract() dynamically in %s on line %d
|
||||||
|
int(1)
|
||||||
|
|
||||||
|
Warning: Cannot call extract() dynamically in %s on line %d
|
||||||
|
int(1)
|
48
Zend/tests/dynamic_call_006.phpt
Normal file
48
Zend/tests/dynamic_call_006.phpt
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
--TEST--
|
||||||
|
Dynamic calls to scope introspection functions are forbidden (function variations)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
function test() {
|
||||||
|
$func = 'extract';
|
||||||
|
$func(['a' => 'b']);
|
||||||
|
|
||||||
|
$func = 'compact';
|
||||||
|
$func(['a']);
|
||||||
|
|
||||||
|
$func = 'parse_str';
|
||||||
|
$func('a=b');
|
||||||
|
|
||||||
|
$func = 'get_defined_vars';
|
||||||
|
$func();
|
||||||
|
|
||||||
|
$func = 'assert';
|
||||||
|
$func('1==2');
|
||||||
|
|
||||||
|
$func = 'func_get_args';
|
||||||
|
$func();
|
||||||
|
|
||||||
|
$func = 'func_get_arg';
|
||||||
|
$func(1);
|
||||||
|
|
||||||
|
$func = 'func_num_args';
|
||||||
|
$func();
|
||||||
|
}
|
||||||
|
test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: Cannot call extract() dynamically in %s on line %d
|
||||||
|
|
||||||
|
Warning: Cannot call compact() dynamically in %s on line %d
|
||||||
|
|
||||||
|
Warning: Cannot call parse_str() with a single argument dynamically in %s on line %d
|
||||||
|
|
||||||
|
Warning: Cannot call get_defined_vars() dynamically in %s on line %d
|
||||||
|
|
||||||
|
Warning: Cannot call assert() with string argument dynamically in %s on line %d
|
||||||
|
|
||||||
|
Warning: Cannot call func_get_args() dynamically in %s on line %d
|
||||||
|
|
||||||
|
Warning: Cannot call func_get_arg() dynamically in %s on line %d
|
||||||
|
|
||||||
|
Warning: Cannot call func_num_args() dynamically in %s on line %d
|
17
Zend/tests/dynamic_call_007.phpt
Normal file
17
Zend/tests/dynamic_call_007.phpt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
--TEST--
|
||||||
|
Dynamic calls to scope introspection functions are forbidden (misoptimization)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
$i = 1;
|
||||||
|
array_map('extract', [['i' => new stdClass]]);
|
||||||
|
$i += 1;
|
||||||
|
var_dump($i);
|
||||||
|
}
|
||||||
|
test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: Cannot call extract() dynamically in %s on line %d
|
||||||
|
int(2)
|
13
Zend/tests/dynamic_call_008.phpt
Normal file
13
Zend/tests/dynamic_call_008.phpt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
--TEST--
|
||||||
|
Don't optimize dynamic call to non-dynamic one if it drops the warning
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
((string) 'extract')(['a' => 42]);
|
||||||
|
}
|
||||||
|
test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: Cannot call extract() dynamically in %s on line %d
|
|
@ -8,6 +8,8 @@ print "- empty ---\n";
|
||||||
$str = "test0123";
|
$str = "test0123";
|
||||||
|
|
||||||
var_dump(empty($str[-1]));
|
var_dump(empty($str[-1]));
|
||||||
|
var_dump(empty($str[-10]));
|
||||||
|
var_dump(empty($str[-4])); // 0
|
||||||
var_dump(empty($str[0]));
|
var_dump(empty($str[0]));
|
||||||
var_dump(empty($str[1]));
|
var_dump(empty($str[1]));
|
||||||
var_dump(empty($str[4])); // 0
|
var_dump(empty($str[4])); // 0
|
||||||
|
@ -17,6 +19,8 @@ var_dump(empty($str[10000]));
|
||||||
// non-numeric offsets
|
// non-numeric offsets
|
||||||
print "- string ---\n";
|
print "- string ---\n";
|
||||||
var_dump(empty($str['-1']));
|
var_dump(empty($str['-1']));
|
||||||
|
var_dump(empty($str['-10']));
|
||||||
|
var_dump(empty($str['-4'])); // 0
|
||||||
var_dump(empty($str['0']));
|
var_dump(empty($str['0']));
|
||||||
var_dump(empty($str['1']));
|
var_dump(empty($str['1']));
|
||||||
var_dump(empty($str['4'])); // 0
|
var_dump(empty($str['4'])); // 0
|
||||||
|
@ -31,6 +35,8 @@ print "- null ---\n";
|
||||||
var_dump(empty($str[null]));
|
var_dump(empty($str[null]));
|
||||||
print "- double ---\n";
|
print "- double ---\n";
|
||||||
var_dump(empty($str[-1.1]));
|
var_dump(empty($str[-1.1]));
|
||||||
|
var_dump(empty($str[-10.5]));
|
||||||
|
var_dump(empty($str[-4.1]));
|
||||||
var_dump(empty($str[-0.8]));
|
var_dump(empty($str[-0.8]));
|
||||||
var_dump(empty($str[-0.1]));
|
var_dump(empty($str[-0.1]));
|
||||||
var_dump(empty($str[0.2]));
|
var_dump(empty($str[0.2]));
|
||||||
|
@ -50,6 +56,8 @@ print "done\n";
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
- empty ---
|
- empty ---
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(false)
|
bool(false)
|
||||||
|
@ -58,6 +66,8 @@ bool(false)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
- string ---
|
- string ---
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(false)
|
bool(false)
|
||||||
|
@ -72,6 +82,8 @@ bool(true)
|
||||||
- null ---
|
- null ---
|
||||||
bool(false)
|
bool(false)
|
||||||
- double ---
|
- double ---
|
||||||
|
bool(false)
|
||||||
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(false)
|
bool(false)
|
||||||
|
|
33
Zend/tests/entry_block_with_predecessors.phpt
Normal file
33
Zend/tests/entry_block_with_predecessors.phpt
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
--TEST--
|
||||||
|
For SSA form the entry block should have no predecessors
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
while (true) {
|
||||||
|
var_dump($a + 1);
|
||||||
|
$a = 1;
|
||||||
|
if (@$i++) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test2() {
|
||||||
|
while (true) {
|
||||||
|
$a = 42;
|
||||||
|
if (@$i++ > 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$a = new stdClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test();
|
||||||
|
test2();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Notice: Undefined variable: a in %s on line %d
|
||||||
|
int(1)
|
||||||
|
int(2)
|
|
@ -11,7 +11,7 @@ function foo1($arg) {
|
||||||
function foo2($arg) {
|
function foo2($arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo3($arg) {
|
function foo3() {
|
||||||
echo $undef3;
|
echo $undef3;
|
||||||
throw new Exception("test");
|
throw new Exception("test");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ function foo1($arg) {
|
||||||
function foo2($arg) {
|
function foo2($arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo3($arg) {
|
function foo3() {
|
||||||
echo $undef3;
|
echo $undef3;
|
||||||
throw new Exception("test");
|
throw new Exception("test");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ function foo1($arg) {
|
||||||
function foo2($arg) {
|
function foo2($arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function foo3($arg) {
|
function foo3() {
|
||||||
error_reporting(E_ALL|E_STRICT);
|
error_reporting(E_ALL|E_STRICT);
|
||||||
echo $undef3;
|
echo $undef3;
|
||||||
throw new Exception("test");
|
throw new Exception("test");
|
||||||
|
|
36
Zend/tests/foreach_list_keyed.phpt
Normal file
36
Zend/tests/foreach_list_keyed.phpt
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
--TEST--
|
||||||
|
foreach with list syntax, keyed
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$points = [
|
||||||
|
["x" => 1, "y" => 2],
|
||||||
|
["x" => 2, "y" => 1]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($points as list("x" => $x, "y" => $y)) {
|
||||||
|
var_dump($x, $y);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
$invertedPoints = [
|
||||||
|
"x" => [1, 2],
|
||||||
|
"y" => [2, 1]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($invertedPoints as list(0 => $row1, 1 => $row2)) {
|
||||||
|
var_dump($row1, $row2);
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
int(1)
|
||||||
|
int(2)
|
||||||
|
int(2)
|
||||||
|
int(1)
|
||||||
|
|
||||||
|
int(1)
|
||||||
|
int(2)
|
||||||
|
int(2)
|
||||||
|
int(1)
|
|
@ -5,7 +5,7 @@ Calling method from array
|
||||||
|
|
||||||
class Hello {
|
class Hello {
|
||||||
public function world($x) {
|
public function world($x) {
|
||||||
echo "Hello, $x\n"; return $this;
|
echo "Hello, $x\n";return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,16 @@ class Magic3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
$f = array('Hello','world');
|
$f = array('Hello','world');
|
||||||
var_dump($f('you'));
|
try {
|
||||||
var_dump(call_user_func($f, 'you'));
|
var_dump($f('you'));
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var_dump(call_user_func($f, 'you'));
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
printf("-----\n");
|
printf("-----\n");
|
||||||
|
|
||||||
|
@ -101,35 +109,31 @@ var_dump(call_user_func($f, 'you'));
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Deprecated: Non-static method Hello::world() should not be called statically in %s on line %d
|
Deprecated: Non-static method Hello::world() should not be called statically in %s on line %d
|
||||||
Hello, you
|
Hello, you
|
||||||
|
Exception: Using $this when not in object context
|
||||||
Notice: Undefined variable: this in %s on line %d
|
|
||||||
NULL
|
|
||||||
|
|
||||||
Deprecated: %son-static method Hello::world() should not be called statically in %s on line %d
|
Deprecated: %son-static method Hello::world() should not be called statically in %s on line %d
|
||||||
Hello, you
|
Hello, you
|
||||||
|
Exception: Using $this when not in object context
|
||||||
Notice: Undefined variable: this in %s on line %d
|
|
||||||
NULL
|
|
||||||
-----
|
-----
|
||||||
Hello, again
|
Hello, again
|
||||||
object(Hello)#1 (0) {
|
object(Hello)#%d (0) {
|
||||||
}
|
}
|
||||||
Hello, again
|
Hello, again
|
||||||
object(Hello)#1 (0) {
|
object(Hello)#%d (0) {
|
||||||
}
|
}
|
||||||
-----
|
-----
|
||||||
Hello, there
|
Hello, there
|
||||||
object(Hello)#2 (0) {
|
object(Hello)#%d (0) {
|
||||||
}
|
}
|
||||||
Hello, there
|
Hello, there
|
||||||
object(Hello)#2 (0) {
|
object(Hello)#%d (0) {
|
||||||
}
|
}
|
||||||
-----
|
-----
|
||||||
Hello, devs
|
Hello, devs
|
||||||
object(Hello)#4 (0) {
|
object(Hello)#%d (0) {
|
||||||
}
|
}
|
||||||
Hello, devs
|
Hello, devs
|
||||||
object(Hello)#4 (0) {
|
object(Hello)#%d (0) {
|
||||||
}
|
}
|
||||||
-----
|
-----
|
||||||
Magic::__call called (foo)!
|
Magic::__call called (foo)!
|
||||||
|
|
10
Zend/tests/func_get_args.phpt
Normal file
10
Zend/tests/func_get_args.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
Testing func_get_args()
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
func_get_args();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Warning: func_get_args(): Called from the global scope - no function context in %s on line 3
|
|
@ -10,9 +10,9 @@ for ($i = 0; $i < 10001; $i++) {
|
||||||
}
|
}
|
||||||
$a[] = "xxx";
|
$a[] = "xxx";
|
||||||
unset($a);
|
unset($a);
|
||||||
var_dump(gc_collect_cycles());
|
var_dump(gc_collect_cycles() > 0);
|
||||||
echo "ok\n";
|
echo "ok\n";
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
int(2)
|
bool(true)
|
||||||
ok
|
ok
|
||||||
|
|
|
@ -12,9 +12,9 @@ for ($i = 0; $i < 10001; $i++) {
|
||||||
unset($b);
|
unset($b);
|
||||||
$a->b = "xxx";
|
$a->b = "xxx";
|
||||||
unset($a);
|
unset($a);
|
||||||
var_dump(gc_collect_cycles());
|
var_dump(gc_collect_cycles() > 0);
|
||||||
echo "ok\n";
|
echo "ok\n";
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
int(2)
|
bool(true)
|
||||||
ok
|
ok
|
||||||
|
|
|
@ -12,9 +12,9 @@ $a->b = "xxx";
|
||||||
unset($c);
|
unset($c);
|
||||||
unset($a);
|
unset($a);
|
||||||
unset($b);
|
unset($b);
|
||||||
var_dump(gc_collect_cycles());
|
var_dump(gc_collect_cycles() > 0);
|
||||||
echo "ok\n";
|
echo "ok\n";
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
int(2)
|
bool(true)
|
||||||
ok
|
ok
|
||||||
|
|
|
@ -10,7 +10,6 @@ class Node {
|
||||||
public $parent;
|
public $parent;
|
||||||
function __construct($name) {
|
function __construct($name) {
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->children = array();
|
|
||||||
$this->parent = null;
|
$this->parent = null;
|
||||||
}
|
}
|
||||||
function insert($node) {
|
function insert($node) {
|
||||||
|
@ -32,12 +31,12 @@ $a->insert($c);
|
||||||
unset($a);
|
unset($a);
|
||||||
unset($b);
|
unset($b);
|
||||||
unset($c);
|
unset($c);
|
||||||
var_dump(gc_collect_cycles());
|
var_dump(gc_collect_cycles() >= 7);
|
||||||
echo "ok\n"
|
echo "ok\n"
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
string(1) "%s"
|
string(1) "%s"
|
||||||
string(1) "%s"
|
string(1) "%s"
|
||||||
string(1) "%s"
|
string(1) "%s"
|
||||||
int(10)
|
bool(true)
|
||||||
ok
|
ok
|
||||||
|
|
45
Zend/tests/generators/gc_with_yield_from.phpt
Normal file
45
Zend/tests/generators/gc_with_yield_from.phpt
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
--TEST--
|
||||||
|
Verify yield from on generators being properly cycle collected
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function root() {
|
||||||
|
global $gens; // create cyclic reference to root
|
||||||
|
try {
|
||||||
|
yield 1;
|
||||||
|
} finally {
|
||||||
|
var_dump($gens);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function gen($x) {
|
||||||
|
global $gens;
|
||||||
|
yield from $gens[] = $x ? gen(--$x) : root();
|
||||||
|
}
|
||||||
|
|
||||||
|
$gen = $gens[] = gen(2);
|
||||||
|
var_dump($gen->current());
|
||||||
|
unset($gen, $gens);
|
||||||
|
print "collect\n";
|
||||||
|
gc_collect_cycles();
|
||||||
|
print "end\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
int(1)
|
||||||
|
collect
|
||||||
|
array(4) {
|
||||||
|
[0]=>
|
||||||
|
object(Generator)#1 (0) {
|
||||||
|
}
|
||||||
|
[1]=>
|
||||||
|
object(Generator)#2 (0) {
|
||||||
|
}
|
||||||
|
[2]=>
|
||||||
|
object(Generator)#3 (0) {
|
||||||
|
}
|
||||||
|
[3]=>
|
||||||
|
object(Generator)#4 (0) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
12
Zend/tests/generators/generator_with_arg_unpacking.phpt
Normal file
12
Zend/tests/generators/generator_with_arg_unpacking.phpt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
--TEST--
|
||||||
|
Generators with arguments unpacking
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
(function() { yield; })(...range(1, 16384));
|
||||||
|
call_user_func_array(function() { yield; }, range(1, 16384));
|
||||||
|
$g = (function() { yield; })(...range(1, 16384));
|
||||||
|
$g = call_user_func_array(function() { yield; }, range(1, 16384));
|
||||||
|
echo "OK\n";
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
OK
|
13
Zend/tests/generators/generator_with_type_check.phpt
Normal file
13
Zend/tests/generators/generator_with_type_check.phpt
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
--TEST--
|
||||||
|
Generator wit type check
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
function gen(array $a) { yield; }
|
||||||
|
gen(42);
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Uncaught TypeError: Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check.php on line 3 and defined in %sgenerator_with_type_check.php:2
|
||||||
|
Stack trace:
|
||||||
|
#0 %sgenerator_with_type_check.php(3): gen(42)
|
||||||
|
#1 {main}
|
||||||
|
thrown in %sgenerator_with_type_check.php on line 2
|
22
Zend/tests/generators/generator_with_type_check_2.phpt
Normal file
22
Zend/tests/generators/generator_with_type_check_2.phpt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
--TEST--
|
||||||
|
Generator wit type check
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
function gen(array $a) { yield; }
|
||||||
|
try {
|
||||||
|
gen(42);
|
||||||
|
} catch (TypeError $e) {
|
||||||
|
echo $e->getMessage()."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
foreach (gen(42) as $val) {
|
||||||
|
var_dump($val);
|
||||||
|
}
|
||||||
|
} catch (TypeError $e) {
|
||||||
|
echo $e->getMessage()."\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check_2.php on line 4
|
||||||
|
Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check_2.php on line 10
|
17
Zend/tests/generators/yield_from_iterator_agregate.phpt
Normal file
17
Zend/tests/generators/yield_from_iterator_agregate.phpt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
--TEST--
|
||||||
|
yield from with an IteratorAggregate
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
class foo implements \IteratorAggregate {
|
||||||
|
public $prop = 1;
|
||||||
|
function getIterator() {
|
||||||
|
var_dump($this->prop);
|
||||||
|
yield;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(function(){
|
||||||
|
yield from new foo;
|
||||||
|
})()->next();
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
int(1)
|
22
Zend/tests/global_with_side_effect_name.phpt
Normal file
22
Zend/tests/global_with_side_effect_name.phpt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
--TEST--
|
||||||
|
Global variable import using a name with side effects
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function sf($arg) {
|
||||||
|
echo "called\n";
|
||||||
|
return $arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
global ${sf("a")};
|
||||||
|
var_dump($a);
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = 42;
|
||||||
|
test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
called
|
||||||
|
int(42)
|
|
@ -10,11 +10,12 @@ class B {
|
||||||
function bar() { A::foo(); }
|
function bar() { A::foo(); }
|
||||||
}
|
}
|
||||||
$b = new B;
|
$b = new B;
|
||||||
$b->bar();
|
try {
|
||||||
|
$b->bar();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
Deprecated: Non-static method A::foo() should not be called statically in %s on line %d
|
Deprecated: Non-static method A::foo() should not be called statically in %s on line %d
|
||||||
|
Exception: Using $this when not in object context
|
||||||
Notice: Undefined variable: this in %s on line %d
|
|
||||||
string(1) "A"
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ foreach ($testvalues as $testvalue) {
|
||||||
}
|
}
|
||||||
echo "\n*** Indexing - Testing reference assignment with key ***\n";
|
echo "\n*** Indexing - Testing reference assignment with key ***\n";
|
||||||
|
|
||||||
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
|
$testvalues=array(null, 0, 1, true, false,0.1,array());
|
||||||
|
|
||||||
foreach ($testvalues as $testvalue) {
|
foreach ($testvalues as $testvalue) {
|
||||||
$testvalue['foo']=&$array;
|
$testvalue['foo']=&$array;
|
||||||
|
@ -20,7 +20,7 @@ foreach ($testvalues as $testvalue) {
|
||||||
}
|
}
|
||||||
echo "*** Indexing - Testing value assignment no key ***\n";
|
echo "*** Indexing - Testing value assignment no key ***\n";
|
||||||
$array=array(1);
|
$array=array(1);
|
||||||
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
|
$testvalues=array(null, 0, 1, true, false,0.1,array());
|
||||||
|
|
||||||
foreach ($testvalues as $testvalue) {
|
foreach ($testvalues as $testvalue) {
|
||||||
$testvalue[]=$array;
|
$testvalue[]=$array;
|
||||||
|
@ -28,7 +28,7 @@ foreach ($testvalues as $testvalue) {
|
||||||
}
|
}
|
||||||
echo "\n*** Indexing - Testing reference assignment no key ***\n";
|
echo "\n*** Indexing - Testing reference assignment no key ***\n";
|
||||||
|
|
||||||
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
|
$testvalues=array(null, 0, 1, true, false,0.1,array());
|
||||||
|
|
||||||
foreach ($testvalues as $testvalue) {
|
foreach ($testvalues as $testvalue) {
|
||||||
$testvalue[]=&$array;
|
$testvalue[]=&$array;
|
||||||
|
@ -63,13 +63,11 @@ array(1) {
|
||||||
int(1)
|
int(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array(1) {
|
|
||||||
["foo"]=>
|
Warning: Illegal string offset 'foo' in %s on line %d
|
||||||
array(1) {
|
|
||||||
[0]=>
|
Notice: Array to string conversion in %s on line %d
|
||||||
int(1)
|
string(1) "A"
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Warning: Illegal string offset 'foo' in %s on line %d
|
Warning: Illegal string offset 'foo' in %s on line %d
|
||||||
|
|
||||||
|
@ -110,13 +108,6 @@ array(1) {
|
||||||
int(1)
|
int(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array(1) {
|
|
||||||
["foo"]=>
|
|
||||||
&array(1) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Warning: Cannot use a scalar value as an array in %s on line %d
|
Warning: Cannot use a scalar value as an array in %s on line %d
|
||||||
float(0.1)
|
float(0.1)
|
||||||
|
@ -151,13 +142,6 @@ array(1) {
|
||||||
int(1)
|
int(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array(1) {
|
|
||||||
[0]=>
|
|
||||||
array(1) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Warning: Cannot use a scalar value as an array in %s on line %d
|
Warning: Cannot use a scalar value as an array in %s on line %d
|
||||||
float(0.1)
|
float(0.1)
|
||||||
|
@ -193,13 +177,6 @@ array(1) {
|
||||||
int(1)
|
int(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
array(1) {
|
|
||||||
[0]=>
|
|
||||||
&array(1) {
|
|
||||||
[0]=>
|
|
||||||
int(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Warning: Cannot use a scalar value as an array in %s on line %d
|
Warning: Cannot use a scalar value as an array in %s on line %d
|
||||||
float(0.1)
|
float(0.1)
|
||||||
|
@ -211,4 +188,4 @@ array(1) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Done
|
Done
|
||||||
|
|
|
@ -17,8 +17,11 @@ class foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
$arr = array('foo', 'abc');
|
$arr = array('foo', 'abc');
|
||||||
$arr();
|
try {
|
||||||
|
$arr();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
echo "Exception: " . $e->getMessage() . "\n";
|
||||||
|
}
|
||||||
$foo = new foo;
|
$foo = new foo;
|
||||||
$arr = array($foo, 'abc');
|
$arr = array($foo, 'abc');
|
||||||
$arr();
|
$arr();
|
||||||
|
@ -28,9 +31,7 @@ $arr();
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
From foo::__callStatic:
|
From foo::__callStatic:
|
||||||
string(3) "abc"
|
string(3) "abc"
|
||||||
|
Exception: Using $this when not in object context
|
||||||
Notice: Undefined variable: this in %s on line %d
|
|
||||||
NULL
|
|
||||||
From foo::__call:
|
From foo::__call:
|
||||||
string(3) "abc"
|
string(3) "abc"
|
||||||
object(foo)#%d (0) {
|
object(foo)#%d (0) {
|
||||||
|
|
17
Zend/tests/inference_infinite_loop.phpt
Normal file
17
Zend/tests/inference_infinite_loop.phpt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
--TEST--
|
||||||
|
Type inference should not result in infinite loop
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
$b = false;
|
||||||
|
do {
|
||||||
|
$a = $a + PHP_INT_MAX + 2;
|
||||||
|
$a = 0;
|
||||||
|
} while ($b);
|
||||||
|
}
|
||||||
|
test();
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Notice: Undefined variable: a in %s on line %d
|
52
Zend/tests/int_conversion_exponents.phpt
Normal file
52
Zend/tests/int_conversion_exponents.phpt
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
--TEST--
|
||||||
|
Integer conversion from scientific notation
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
var_dump((int)"1.2345e9");
|
||||||
|
var_dump((int)"-1.2345e9");
|
||||||
|
var_dump(intval("1.2345e9"));
|
||||||
|
var_dump(intval("-1.2345e9"));
|
||||||
|
var_dump("1.2345e9" % PHP_INT_MAX);
|
||||||
|
var_dump("-1.2345e9" % PHP_INT_MIN);
|
||||||
|
var_dump("1.2345e9" | 0);
|
||||||
|
var_dump("-1.2345e9" | 0);
|
||||||
|
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
var_dump((int)" 1.2345e9 abc");
|
||||||
|
var_dump((int)" -1.2345e9 abc");
|
||||||
|
var_dump(intval(" 1.2345e9 abc"));
|
||||||
|
var_dump(intval(" -1.2345e9 abc"));
|
||||||
|
var_dump(" 1.2345e9 abc" % PHP_INT_MAX);
|
||||||
|
var_dump(" -1.2345e9 abc" % PHP_INT_MIN);
|
||||||
|
var_dump(" 1.2345e9 abc" | 0);
|
||||||
|
var_dump(" -1.2345e9 abc" | 0);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
int(1234500000)
|
||||||
|
int(-1234500000)
|
||||||
|
int(1234500000)
|
||||||
|
int(-1234500000)
|
||||||
|
int(1234500000)
|
||||||
|
int(-1234500000)
|
||||||
|
int(1234500000)
|
||||||
|
int(-1234500000)
|
||||||
|
|
||||||
|
int(1234500000)
|
||||||
|
int(-1234500000)
|
||||||
|
int(1234500000)
|
||||||
|
int(-1234500000)
|
||||||
|
|
||||||
|
Notice: A non well formed numeric value encountered in %s on line %d
|
||||||
|
int(1234500000)
|
||||||
|
|
||||||
|
Notice: A non well formed numeric value encountered in %s on line %d
|
||||||
|
int(-1234500000)
|
||||||
|
|
||||||
|
Notice: A non well formed numeric value encountered in %s on line %d
|
||||||
|
int(1234500000)
|
||||||
|
|
||||||
|
Notice: A non well formed numeric value encountered in %s on line %d
|
||||||
|
int(-1234500000)
|
|
@ -8,6 +8,7 @@ print "- isset ---\n";
|
||||||
$str = "test0123";
|
$str = "test0123";
|
||||||
|
|
||||||
var_dump(isset($str[-1]));
|
var_dump(isset($str[-1]));
|
||||||
|
var_dump(isset($str[-10]));
|
||||||
var_dump(isset($str[0]));
|
var_dump(isset($str[0]));
|
||||||
var_dump(isset($str[1]));
|
var_dump(isset($str[1]));
|
||||||
var_dump(isset($str[4])); // 0
|
var_dump(isset($str[4])); // 0
|
||||||
|
@ -17,6 +18,7 @@ var_dump(isset($str[10000]));
|
||||||
// non-numeric offsets
|
// non-numeric offsets
|
||||||
print "- string ---\n";
|
print "- string ---\n";
|
||||||
var_dump(isset($str['-1']));
|
var_dump(isset($str['-1']));
|
||||||
|
var_dump(isset($str['-10']));
|
||||||
var_dump(isset($str['0']));
|
var_dump(isset($str['0']));
|
||||||
var_dump(isset($str['1']));
|
var_dump(isset($str['1']));
|
||||||
var_dump(isset($str['4'])); // 0
|
var_dump(isset($str['4'])); // 0
|
||||||
|
@ -31,6 +33,7 @@ print "- null ---\n";
|
||||||
var_dump(isset($str[null]));
|
var_dump(isset($str[null]));
|
||||||
print "- double ---\n";
|
print "- double ---\n";
|
||||||
var_dump(isset($str[-1.1]));
|
var_dump(isset($str[-1.1]));
|
||||||
|
var_dump(isset($str[-10.5]));
|
||||||
var_dump(isset($str[-0.8]));
|
var_dump(isset($str[-0.8]));
|
||||||
var_dump(isset($str[-0.1]));
|
var_dump(isset($str[-0.1]));
|
||||||
var_dump(isset($str[0.2]));
|
var_dump(isset($str[0.2]));
|
||||||
|
@ -50,6 +53,7 @@ print "done\n";
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
- isset ---
|
- isset ---
|
||||||
|
bool(true)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
|
@ -58,6 +62,7 @@ bool(true)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(false)
|
bool(false)
|
||||||
- string ---
|
- string ---
|
||||||
|
bool(true)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
|
@ -72,6 +77,7 @@ bool(false)
|
||||||
- null ---
|
- null ---
|
||||||
bool(true)
|
bool(true)
|
||||||
- double ---
|
- double ---
|
||||||
|
bool(true)
|
||||||
bool(false)
|
bool(false)
|
||||||
bool(true)
|
bool(true)
|
||||||
bool(true)
|
bool(true)
|
||||||
|
|
27
Zend/tests/jump16.phpt
Normal file
27
Zend/tests/jump16.phpt
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
--TEST--
|
||||||
|
jump 16: goto into try/catch
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
goto a;
|
||||||
|
try {
|
||||||
|
echo "1";
|
||||||
|
a:
|
||||||
|
echo "2";
|
||||||
|
throw new Exception();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "3";
|
||||||
|
}
|
||||||
|
echo "4";
|
||||||
|
goto b;
|
||||||
|
try {
|
||||||
|
echo "5";
|
||||||
|
throw new Exception();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "6";
|
||||||
|
b:
|
||||||
|
echo "7";
|
||||||
|
}
|
||||||
|
echo "8\n";
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
23478
|
22
Zend/tests/jump17.phpt
Normal file
22
Zend/tests/jump17.phpt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
--TEST--
|
||||||
|
jump 17: goto into try/catch with finally
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
goto b;
|
||||||
|
try {
|
||||||
|
echo "1";
|
||||||
|
a:
|
||||||
|
echo "2";
|
||||||
|
throw new Exception();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "3";
|
||||||
|
b:
|
||||||
|
echo "4";
|
||||||
|
} finally {
|
||||||
|
echo "5";
|
||||||
|
c:
|
||||||
|
echo "6";
|
||||||
|
}
|
||||||
|
echo "7\n";
|
||||||
|
--EXPECT--
|
||||||
|
4567
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
list($a, list($b)) = array(new stdclass, array(new stdclass));
|
list($a, list($b)) = array(new stdclass, array(new stdclass));
|
||||||
var_dump($a, $b);
|
var_dump($a, $b);
|
||||||
|
[$a, [$b]] = array(new stdclass, array(new stdclass));
|
||||||
|
var_dump($a, $b);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
|
@ -12,3 +14,7 @@ object(stdClass)#1 (0) {
|
||||||
}
|
}
|
||||||
object(stdClass)#2 (0) {
|
object(stdClass)#2 (0) {
|
||||||
}
|
}
|
||||||
|
object(stdClass)#3 (0) {
|
||||||
|
}
|
||||||
|
object(stdClass)#4 (0) {
|
||||||
|
}
|
||||||
|
|
10
Zend/tests/list_008.phpt
Normal file
10
Zend/tests/list_008.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
Assignment to invalid list() value
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
[42] = [1];
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Assignments can only happen to writable values in %s on line %d
|
14
Zend/tests/list_009.phpt
Normal file
14
Zend/tests/list_009.phpt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
--TEST--
|
||||||
|
list with by-reference assignment should fail
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$a = [1];
|
||||||
|
[&$foo] = $a;
|
||||||
|
$foo = 2;
|
||||||
|
|
||||||
|
var_dump($a);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: [] and list() assignments cannot be by reference in %s on line %d
|
11
Zend/tests/list_010.phpt
Normal file
11
Zend/tests/list_010.phpt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
--TEST--
|
||||||
|
Do not allow mixing [] and list()
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
list([$a]) = [[1]];
|
||||||
|
var_dump($a);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Cannot mix [] and list() in %s on line %d
|
10
Zend/tests/list_011.phpt
Normal file
10
Zend/tests/list_011.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
Disallow list() usage as if it were an array
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
var_dump(list(1, 2, 3));
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Parse error: syntax error, unexpected ')', expecting '=' in %s on line %d
|
10
Zend/tests/list_012.phpt
Normal file
10
Zend/tests/list_012.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
Disallow empty elements in normal arrays
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
var_dump([, 1, 2]);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Cannot use empty array elements in arrays in %s on line %d
|
10
Zend/tests/list_013.phpt
Normal file
10
Zend/tests/list_013.phpt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
--TEST--
|
||||||
|
Disallow tail empty elements in normal arrays
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
var_dump([1, 2, ,]);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECTF--
|
||||||
|
Fatal error: Cannot use empty array elements in arrays in %s on line %d
|
71
Zend/tests/list_keyed.phpt
Normal file
71
Zend/tests/list_keyed.phpt
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
--TEST--
|
||||||
|
list() with keys
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$antonyms = [
|
||||||
|
"good" => "bad",
|
||||||
|
"happy" => "sad",
|
||||||
|
];
|
||||||
|
|
||||||
|
list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms;
|
||||||
|
var_dump($good_antonym, $happy_antonym);
|
||||||
|
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
$powersOfTwo = [
|
||||||
|
1 => 2,
|
||||||
|
2 => 4,
|
||||||
|
3 => 8
|
||||||
|
];
|
||||||
|
|
||||||
|
list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo;
|
||||||
|
var_dump($two_1, $two_2, $two_3);
|
||||||
|
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
$contrivedMixedKeyTypesExample = [
|
||||||
|
7 => "the best PHP version",
|
||||||
|
"elePHPant" => "the cutest mascot"
|
||||||
|
];
|
||||||
|
|
||||||
|
list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample;
|
||||||
|
var_dump($seven, $elePHPant);
|
||||||
|
|
||||||
|
echo PHP_EOL;
|
||||||
|
|
||||||
|
$allTogetherNow = [
|
||||||
|
"antonyms" => $antonyms,
|
||||||
|
"powersOfTwo" => $powersOfTwo,
|
||||||
|
"contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample
|
||||||
|
];
|
||||||
|
|
||||||
|
list(
|
||||||
|
"antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym),
|
||||||
|
"powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3),
|
||||||
|
"contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant)
|
||||||
|
) = $allTogetherNow;
|
||||||
|
|
||||||
|
var_dump($good_antonym, $happy_antonym);
|
||||||
|
var_dump($two_1, $two_2, $two_3);
|
||||||
|
var_dump($seven, $elePHPant);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
string(3) "bad"
|
||||||
|
string(3) "sad"
|
||||||
|
|
||||||
|
int(2)
|
||||||
|
int(4)
|
||||||
|
int(8)
|
||||||
|
|
||||||
|
string(20) "the best PHP version"
|
||||||
|
string(17) "the cutest mascot"
|
||||||
|
|
||||||
|
string(3) "bad"
|
||||||
|
string(3) "sad"
|
||||||
|
int(2)
|
||||||
|
int(4)
|
||||||
|
int(8)
|
||||||
|
string(20) "the best PHP version"
|
||||||
|
string(17) "the cutest mascot"
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue