Merge branch 'master' of git.php.net:php-src

* 'master' of git.php.net:php-src: (641 commits)
  fix unix/win dir separators
  Fix bug #63173: Crash when invoking invalid array callback
  compile out example plugin in a release build
  change public key setting to PERDIR and finish code that allows to set the key file programatically per mysqli_options()
  remove old unicode code, that is was compiled out by using a macro
  Add SHA256 authentication support - password hashing to mysqlnd Automatic switchover to SSL with plain-text password is not part of this
  Correct the test summary
  Fixed bug #60723 (error_log error time has changed to UTC ignoring default timezo)
  Fixed bug #60723 (error_log error time has changed to UTC ignoring default timezo)
  Add NEWS/UPGRADING for previous change
  Simplify set_error_handler/set_exception_handler code
  Return previous error handler when resetting the error handler
  Allow resetting the error handler
  Revert error/exception handler changes
  Fixed bug #63132
  Avoid calling select if maxfd returned by curl_multi_fdset is -1
  Add CURLOPT_READDATA which was removed by mistake
  Fixing NEWS file
  Fixed bug #63111 (is_callable() lies for abstract static method)
  updated lib versions
  ...
This commit is contained in:
Jerome Loyet 2012-09-28 00:06:13 +02:00
commit ca6273240e
973 changed files with 30446 additions and 33637 deletions

1
.gitattributes vendored
View File

@ -15,6 +15,7 @@ ext/dba/libflatfile/flatfile.c ident
ext/dba/libcdb/cdb_make.c ident
ext/dba/libcdb/cdb.c ident
ext/filter/filter.c ident
ext/zip/php_zip.c ident
README.input_filter ident
run-tests.php ident
sapi/nsapi/nsapi.c ident

24
.travis.yml Normal file
View File

@ -0,0 +1,24 @@
language: php
php:
# We only specify one version so we only get one worker
- 5.4
notifications:
email: false
env:
- REPORT_EXIT_STATUS=1 TEST_PHP_EXECUTABLE=./sapi/cli/php
before_script:
# Compile PHP
- ./travis/compile.sh
# Setup Extensions
- . ./travis/ext/mysql/setup.sh
- . ./travis/ext/mysqli/setup.sh
- . ./travis/ext/pdo_mysql/setup.sh
- . ./travis/ext/pgsql/setup.sh
- . ./travis/ext/pdo_pgsql/setup.sh
# Run PHPs run-tests.php
script: ./sapi/cli/php run-tests.php -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP"

View File

@ -2,11 +2,11 @@
PHP Coding Standards
========================
This file lists several standards that any programmer, adding or changing
code in PHP, should follow. Since this file was added at a very late
This file lists several standards that any programmer adding or changing
code in PHP should follow. Since this file was added at a very late
stage of the development of PHP v3.0, the code base does not (yet) fully
follow it, but it's going in that general direction. Since we are now
well into the version 4 releases, many sections have been recoded to use
well into version 5 releases, many sections have been recoded to use
these rules.
Code Implementation

202
INSTALL
View File

@ -24,6 +24,7 @@ Installing PHP
+ Installing a PHP extension on Windows
+ Compiling shared PECL extensions with the pecl command
+ Compiling shared PECL extensions with phpize
+ php-config
+ Compiling PECL extensions statically into PHP
* Problems?
+ Read the FAQ
@ -83,7 +84,7 @@ General Installation Considerations
With PHP you can also write desktop GUI applications using the PHP-GTK
extension. This is a completely different approach than writing web
pages, as you do not output any HTML, but manage windows and objects
within them. For more information about PHP-GTK, please » visit the
within them. For more information about PHP-GTK, please » visit the
site dedicated to this extension. PHP-GTK is not included in the
official PHP distribution.
@ -92,9 +93,9 @@ General Installation Considerations
will also find information on the command line executable in the
following sections.
PHP source code and binary distributions for Windows can be found at »
http://www.php.net/downloads.php. We recommend you to choose a » mirror
nearest to you for downloading the distributions.
PHP source code and binary distributions for Windows can be found at
» http://www.php.net/downloads.php. We recommend you to choose a
» mirror nearest to you for downloading the distributions.
__________________________________________________________________
__________________________________________________________________
@ -140,9 +141,9 @@ Table of Contents
* A web server
* Any module specific components (such as GD, PDF libs, etc.)
When building directly from SVN sources or after custom modifications
When building directly from Git sources or after custom modifications
you might also need:
* autoconf: 2.13
* autoconf: 2.13+ (for PHP < 5.4.0), 2.59+ (for PHP >= 5.4.0)
* automake: 1.4+
* libtool: 1.4.x+ (except 1.4.2)
* re2c: Version 0.13.4 or newer
@ -375,12 +376,12 @@ Apache 2.x on Unix systems
For information on why, read the related FAQ entry on using Apache2
with a threaded MPM
The » Apache Documentation is the most authoritative source of
The » Apache Documentation is the most authoritative source of
information on the Apache 2.x server. More information about
installation options for Apache may be found there.
The most recent version of Apache HTTP Server may be obtained from »
Apache download site, and a fitting PHP version from the above
The most recent version of Apache HTTP Server may be obtained from
» Apache download site, and a fitting PHP version from the above
mentioned places. This quick guide covers only the basics to get
started with Apache 2.x and PHP. For more information read the » Apache
Documentation. The version numbers have been omitted here, to ensure
@ -498,7 +499,7 @@ service httpd restart
This should not be undertaken without being aware of the consequences
of this decision, and having at least a fair understanding of the
implications. The Apache documentation regarding » MPM-Modules
implications. The Apache documentation regarding » MPM-Modules
discusses MPMs in a great deal more detail.
Note:
@ -520,7 +521,7 @@ Lighttpd 1.4 on Unix systems
This section contains notes and hints specific to Lighttpd 1.4 installs
of PHP on Unix systems.
Please use the » Lighttpd trac to learn how to install Lighttpd
Please use the » Lighttpd trac to learn how to install Lighttpd
properly before continuing.
Fastcgi is the preferred SAPI to connect PHP and Lighttpd. Fastcgi is
@ -627,15 +628,15 @@ Sun, iPlanet and Netscape servers on Sun Solaris
current web servers read the note about subrequests.
You can find more information about setting up PHP for the Netscape
Enterprise Server (NES) here: »
http://benoit.noss.free.fr/php/install-php4.html
Enterprise Server (NES) here:
» http://benoit.noss.free.fr/php/install-php4.html
To build PHP with Sun JSWS/Sun ONE WS/iPlanet/Netscape web servers,
enter the proper install directory for the --with-nsapi=[DIR] option.
The default directory is usually /opt/netscape/suitespot/. Please also
read /php-xxx-version/sapi/nsapi/nsapi-readme.txt.
1. Install the following packages from » http://www.sunfreeware.com/
1. Install the following packages from » http://www.sunfreeware.com/
or another download site:
+ autoconf-2.13
+ automake-1.4
@ -837,7 +838,7 @@ Testing
Using Variables
Some server supplied environment variables are not defined in the
current » CGI/1.1 specification. Only the following variables are
current » CGI/1.1 specification. Only the following variables are
defined there: AUTH_TYPE, CONTENT_LENGTH, CONTENT_TYPE,
GATEWAY_INTERFACE, PATH_INFO, PATH_TRANSLATED, QUERY_STRING,
REMOTE_ADDR, REMOTE_HOST, REMOTE_IDENT, REMOTE_USER, REQUEST_METHOD,
@ -855,20 +856,20 @@ HP-UX specific installation notes
There are two main options for installing PHP on HP-UX systems. Either
compile it, or install a pre-compiled binary.
Official pre-compiled packages are located here: »
http://software.hp.com/
Official pre-compiled packages are located here:
» http://software.hp.com/
Until this manual section is rewritten, the documentation about
compiling PHP (and related extensions) on HP-UX systems has been
removed. For now, consider reading the following external resource: »
Building Apache and PHP on HP-UX 11.11
removed. For now, consider reading the following external resource:
» Building Apache and PHP on HP-UX 11.11
__________________________________________________________________
__________________________________________________________________
OpenBSD installation notes
This section contains notes and hints specific to installing PHP on »
OpenBSD 3.6.
This section contains notes and hints specific to installing PHP on
» OpenBSD 3.6.
Using Binary Packages
@ -900,12 +901,12 @@ Using Binary Packages
(install the PEAR libraries)
# pkg_add php4-pear-4.3.8.tgz
Read the » packages(7) manual page for more information about binary
Read the » packages(7) manual page for more information about binary
packages on OpenBSD.
Using Ports
You can also compile up PHP from source using the » ports tree.
You can also compile up PHP from source using the » ports tree.
However, this is only recommended for users familiar with OpenBSD. The
PHP 4 port is split into two sub-directories: core and extensions. The
extensions directory generates sub-packages for all of the supported
@ -926,7 +927,7 @@ Common Problems
automatically installs into the correct chroot directories, so no
special modification is needed there. More information on the
OpenBSD Apache is available in the » OpenBSD FAQ.
* The OpenBSD 3.6 package for the » gd extension requires XFree86 to
* The OpenBSD 3.6 package for the » gd extension requires XFree86 to
be installed. If you do not wish to use some of the font features
that require X11, install the php4-gd-4.3.8-no_x11.tgz package
instead.
@ -951,18 +952,26 @@ Required software
Solaris installs often lack C compilers and their related tools. Read
this FAQ for information on why using GNU versions for some of these
tools is necessary. The required software is as follows:
tools is necessary.
For unpacking the PHP distribution you need
* tar
* gzip or
* bzip2
For compiling PHP you need
* gcc (recommended, other C compilers may work)
* make
* flex
* GNU sed
For building extra extensions or hacking the code of PHP you might also
need
* flex (up to PHP 5.2)
* re2c
* bison
* m4
* autoconf
* automake
* perl
* gzip
* tar
* GNU sed
In addition, you will need to install (and possibly compile) any
additional software specific to your configuration, such as Oracle or
@ -971,14 +980,16 @@ Required software
Using Packages
You can simplify the Solaris install process by using pkgadd to install
most of your needed components.
most of your needed components. The Image Packaging System (IPS) for
Solaris 11 Express also contains most of the required components for
installation using the pkg command.
__________________________________________________________________
__________________________________________________________________
Debian GNU/Linux installation notes
This section contains notes and hints specific to installing PHP on »
Debian GNU/Linux.
This section contains notes and hints specific to installing PHP on
» Debian GNU/Linux.
Warning
Unofficial builds from third-parties are not supported here. Any bugs
@ -1205,6 +1216,7 @@ Table of Contents
* Installing a PHP extension on Windows
* Compiling shared PECL extensions with the pecl command
* Compiling shared PECL extensions with phpize
* php-config
* Compiling PECL extensions statically into PHP
__________________________________________________________________
@ -1227,8 +1239,8 @@ Introduction to PECL Installations
To this php.ini file, or through the use of the dl() function.
When building PHP modules, it's important to have known-good versions
of the required tools (autoconf, automake, libtool, etc.) See the »
Anonymous SVN Instructions for details on the required tools, and
of the required tools (autoconf, automake, libtool, etc.) See the
» Anonymous Git Instructions for details on the required tools, and
required versions.
__________________________________________________________________
__________________________________________________________________
@ -1247,7 +1259,7 @@ Downloading PECL extensions
the PECL web site are available for download and installation using
the » pecl command. Specific revisions may also be specified.
* SVN Most PECL extensions also reside in SVN. A web-based view may
be seen at » http://svn.php.net/viewvc/pecl/. To download straight
be seen at » http://svn.php.net/viewvc/pecl/. To download straight
from SVN, the following sequence of commands may be used:
$ svn checkout http://svn.php.net/repository/pecl/extname/trunk
extname
@ -1279,7 +1291,7 @@ Where to find an extension?
PHP extensions are usually called "php_*.dll" (where the star
represents the name of the extension) and they are located under the
"PHP\ext" ("PHP\extensions" in PHP4) folder.
"PHP\ext" ("PHP\extensions" in PHP 4) folder.
PHP ships with the extensions most useful to the majority of
developers. They are called "core" extensions.
@ -1365,7 +1377,7 @@ Resolving problems
Compiling shared PECL extensions with the pecl command
PECL makes it easy to create shared PHP extensions. Using the » pecl
PECL makes it easy to create shared PHP extensions. Using the » pecl
command, do the following:
$ pecl install extname
@ -1424,6 +1436,51 @@ $ make
__________________________________________________________________
__________________________________________________________________
php-config
php-config is a simple shell script for obtaining information about the
installed PHP configuration.
When compiling extensions, if you have multiple PHP versions installed,
you may specify for which installation you'd like to build by using the
--with-php-config option during configuration, specifying the path of
the respective php-config script.
The list of command line options provided by the php-config script can
be queried anytime by running php-config with the -h switch:
Usage: /usr/local/bin/php-config [OPTION]
Options:
--prefix [...]
--includes [...]
--ldflags [...]
--libs [...]
--extension-dir [...]
--include-dir [...]
--php-binary [...]
--php-sapis [...]
--configure-options [...]
--version [...]
--vernum [...]
CAPTION: Command line options
Option Description
--prefix Directory prefix where PHP is installed, e.g. /usr/local
--includes List of -I options with all include files
--ldflags LD Flags which PHP was compiled with
--libs Extra libraries which PHP was compiled with
--extension-dir Directory where extensions are searched by default
--include-dir Directory prefix where header files are installed by
default
--php-binary Full path to php CLI or CGI binary
--php-sapis Show all SAPI modules available
--configure-options Configure options to recreate configuration of
current PHP installation
--version PHP version
--vernum PHP version as integer
__________________________________________________________________
__________________________________________________________________
Compiling PECL extensions statically into PHP
You might find that you need to build a PECL extension statically into
@ -1485,11 +1542,11 @@ Other problems
If you are still stuck, someone on the PHP installation mailing list
may be able to help you. You should check out the archive first, in
case someone already answered someone else who had the same problem as
you. The archives are available from the support page on »
http://www.php.net/support.php. To subscribe to the PHP installation
mailing list, send an empty mail to »
php-install-subscribe@lists.php.net. The mailing list address is »
php-install@lists.php.net.
you. The archives are available from the support page on
» http://www.php.net/support.php. To subscribe to the PHP installation
mailing list, send an empty mail to
» php-install-subscribe@lists.php.net. The mailing list address is
» php-install@lists.php.net.
If you want to get help on the mailing list, please try to be precise
and give the necessary details about your environment (which operating
@ -1504,11 +1561,11 @@ Bug reports
If you think you have found a bug in PHP, please report it. The PHP
developers probably don't know about it, and unless you report it,
chances are it won't be fixed. You can report bugs using the
bug-tracking system at » http://bugs.php.net/. Please do not send bug
bug-tracking system at » http://bugs.php.net/. Please do not send bug
reports in mailing list or personal letters. The bug system is also
suitable to submit feature requests.
Read the » How to report a bug document before submitting any bug
Read the » How to report a bug document before submitting any bug
reports!
__________________________________________________________________
__________________________________________________________________
@ -1528,14 +1585,14 @@ The configuration file
The configuration file (php.ini) is read when PHP starts up. For the
server module versions of PHP, this happens only once when the web
server is started. For the CGI and CLI version, it happens on every
server is started. For the CGI and CLI versions, it happens on every
invocation.
php.ini is searched in these locations (in order):
php.ini is searched for in these locations (in order):
* SAPI module specific location (PHPIniDir directive in Apache 2, -c
command line option in CGI and CLI, php_ini parameter in NSAPI,
PHP_INI_PATH environment variable in THTTPD)
* The PHPRC environment variable. Before PHP 5.2.0 this was checked
* The PHPRC environment variable. Before PHP 5.2.0, this was checked
after the registry key mentioned below.
* As of PHP 5.2.0, the location of the php.ini file can be set for
different versions of PHP. The following registry keys are examined
@ -1543,33 +1600,33 @@ The configuration file
[HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x.y] and
[HKEY_LOCAL_MACHINE\SOFTWARE\PHP\x], where x, y and z mean the PHP
major, minor and release versions. If there is a value for
IniFilePath in these keys, then the first one found will be used as
the location of the php.ini (Windows only).
IniFilePath in any of these keys, the first one found will be used
as the location of the php.ini (Windows only).
* [HKEY_LOCAL_MACHINE\SOFTWARE\PHP], value of IniFilePath (Windows
only).
* Current working directory (except CLI)
* Current working directory (except CLI).
* The web server's directory (for SAPI modules), or directory of PHP
(otherwise in Windows)
(otherwise in Windows).
* Windows directory (C:\windows or C:\winnt) (for Windows), or
--with-config-file-path compile time option
--with-config-file-path compile time option.
If php-SAPI.ini exists (where SAPI is used SAPI, so the filename is
e.g. php-cli.ini or php-apache.ini), it's used instead of php.ini. SAPI
name can be determined by php_sapi_name().
If php-SAPI.ini exists (where SAPI is the SAPI in use, so, for example,
php-cli.ini or php-apache.ini), it is used instead of php.ini. The SAPI
name can be determined with php_sapi_name().
Note:
The Apache web server changes the directory to root at startup
The Apache web server changes the directory to root at startup,
causing PHP to attempt to read php.ini from the root filesystem if
it exists.
The php.ini directives handled by extensions are documented
respectively on the pages of the extensions themselves. The list of the
core directives is available in the appendix. Probably not all PHP
directives are documented in the manual though. For a complete list of
The php.ini directives handled by extensions are documented on the
respective pages of the extensions themselves. A list of the core
directives is available in the appendix. Not all PHP directives are
necessarily documented in this manual: for a complete list of
directives available in your PHP version, please read your well
commented php.ini file. Alternatively, you may find the » the latest
php.ini from SVN helpful too.
commented php.ini file. Alternatively, you may find » the latest
php.ini from Git helpful too.
Example #1 php.ini example
; any text on a line after an unquoted semicolon (;) is ignored
@ -1635,12 +1692,13 @@ Where a configuration setting may be set
CAPTION: Definition of PHP_INI_* modes
Mode Value Meaning
PHP_INI_USER 1 Entry can be set in user scripts (like with ini_set())
or in the Windows registry
PHP_INI_PERDIR 6 Entry can be set in php.ini, .htaccess or httpd.conf
PHP_INI_SYSTEM 4 Entry can be set in php.ini or httpd.conf
PHP_INI_ALL 7 Entry can be set anywhere
Mode Meaning
PHP_INI_USER Entry can be set in user scripts (like with ini_set()) or
in the Windows registry. Since PHP 5.3, entry can be set in .user.ini
PHP_INI_PERDIR Entry can be set in php.ini, .htaccess, httpd.conf or
.user.ini (since PHP 5.3)
PHP_INI_SYSTEM Entry can be set in php.ini or httpd.conf
PHP_INI_ALL Entry can be set anywhere
__________________________________________________________________
__________________________________________________________________
@ -1788,13 +1846,9 @@ Installation
each request to play in, further weaknesses are introduced into
PHP's system.
If you feel you have to use a threaded MPM, look at a FastCGI
If you want to use a threaded MPM, look at a FastCGI
configuration where PHP is running in its own memory space.
And finally, this warning against using a threaded MPM is not as
strong for Windows systems because most libraries on that
platform tend to be threadsafe.
Unix/Windows: Where should my php.ini file be located?
By default on Unix it should be in /usr/local/lib which is
<install-path>/lib. Most people will want to change this at

34
NEWS
View File

@ -3,20 +3,33 @@ PHP NEWS
?? ??? 201?, PHP 5.5.0
- General improvements:
. Add generators and coroutines (https://wiki.php.net/rfc/generators).
(Nikita Popov)
. Support list in foreach (https://wiki.php.net/rfc/foreachlist). (Laruence)
. Implemented 'finally' keyword (https://wiki.php.net/rfc/finally). (Laruence)
. Drop Windows XP and 2003 support. (Pierre)
. World domination
. Improve set_exception_handler while doing reset.(Laruence)
. Support constant array/string dereferencing. (Laruence)
. Add support for using empty() on the result of function calls and
other expressions (https://wiki.php.net/rfc/empty_isset_exprs).
(Nikita Popov)
- Calendar:
. Fixed bug #54254 (cal_from_jd returns month = 6 when there is only one Adar)
(Stas, Eitan Mosenkis).
- Core:
. Added boolval(). (Jille Timmermans).
. Fixed bug #18556 (Engine uses locale rules to handle class names). (Stas)
. Fixed bug #61681 (Malformed grammar). (Nikita Popov, Etienne, Laruence).
. Fixed bug #61038 (unpack("a5", "str\0\0") does not work as expected).
(srgoogleguy, Gustavo)
. Implemented FR #60738 (Allow 'set_error_handler' to handle NULL).
(Laruence, Nikita Popov)
. Return previous handler when passing NULL to set_error_handler and
set_exception_handler. (Nikita Popov)
. Added optional second argument for assert() to specify custom message. Patch
by Lonny Kapelushnik (lonny@lonnylot.com). (Lars)
- cURL:
. Added support for CURLOPT_FTP_RESPONSE_TIMEOUT, CURLOPT_APPEND,
@ -38,9 +51,20 @@ PHP NEWS
CURLOPT_TRANSFER_ENCODING, CURLOPT_DNS_SERVERS and CURLOPT_USE_SSL.
(Pierrick)
. Fixed bug #55635 (CURLOPT_BINARYTRANSFER no longer used. The constant
still exists for backward compatibility but is doing nothing). (Pierrick)
still exists for backward compatibility but is doing nothing). (Pierrick)
. Fixed bug #54995 (Missing CURLINFO_RESPONSE_CODE support). (Pierrick)
- Datetime
. Fixed bug #61642 (modify("+5 weekdays") returns Sunday).
(Dmitri Iouchtchenko)
- Hash
. Added support for PBKDF2 via hash_pbkdf2(). (Anthony Ferrara)
- MCrypt
. mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb() now throw
E_DEPRECATED. (GoogleGuy)
- MySQLi
. Dropped support for LOAD DATA LOCAL INFILE handlers when using libmysql.
Known for stability problems. (Andrey)
@ -52,4 +76,10 @@ PHP NEWS
- pgsql
. Added pg_escape_literal() and pg_escape_identifier() (Yasuo)
- Tokenizer:
. Fixed bug #60097 (token_get_all fails to lex nested heredoc). (Nikita Popov)
- Zip:
. Upgraded libzip to 0.10.1 (Anatoliy)
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>

View File

@ -127,33 +127,34 @@ Rolling a stable release
2. Bump the version numbers in ``main/php_version.h``, ``configure.in`` and possibly ``NEWS``.
3. **Merge** all related sections in NEWS (f.e. merge the 4.4.1RC1 and 4.4.0 sections)
3. **Merge** all related sections in NEWS (f.e. merge the 5.4.1RC1 and 5.4.0 sections)
4. Commit those changes
5. run the "scripts/dev/credits" script in php-src and commit the changes in the
credits files in ext/standard.
6. tag the repository with the version f.e. "``cvs tag php_4_4_1``"
6. tag the repository with the version f.e. "``git tag -s php-5.4.1``"
(of course, you need to change that to the version you're rolling an RC for).
When making 5.X release, you need to tag the Zend directory separately!!
7. Bump up the version numbers in ``main/php_version.h``, ``configure.in`` and
possibly ``NEWS`` again, to the **next** version. F.e. if the release candidate
was "4.4.1RC1" then the new one should be "4.4.1RC2-dev" - regardless if we get
was "5.4.1RC1" then the new one should be "5.4.1RC2-dev" - regardless if we get
a new RC or not. This is to make sure ``version_compare()`` can correctly work.
8. Commit those changes
9. Log in onto the snaps box and go into the correct tree (f.e. the PHP_4_4
branch if you're rolling 4.4.x releases).
9. Log in onto the snaps box and go into the correct tree (f.e. the PHP-5.4
branch if you're rolling 5.5.x releases).
10. You do not have to update the tree, but of course you can with "``cvs up -dP``".
10. You do not have to update the tree, but of course you can with "``git pull
origin <branch>``".
11. run: ``./makedist php 4.4.1``, this will export the tree, create configure
11. run: ``./makedist php 5.4.1``, this will export the tree, create configure
and build two tarballs (one gz and one bz2).
12. Commit those two tarballs to CVS (phpweb/distributions)
12. Commit those two tarballs to Git (php-distributions.git)
13. Once the release has been tagged, contact the PHP Windows development team
(internals-win@lists.php.net) so that Windows binaries can be created. Once
@ -171,6 +172,9 @@ Getting the stable release announced
a. ``php bin/bumpRelease 5`` (or ``php bin/bumpRelease 4`` for PHP4)
b. In case multiple PHP minor versions are in active development you have
to manually copy the old information to include/releases.inc
2. Edit ``phpweb/include/version.inc`` and change (X=major release number):
a. ``$PHP_X_VERSION`` to the correct version
@ -187,7 +191,7 @@ Getting the stable release announced
f. if the windows builds aren't ready yet prefix the "windows" key with a dot (".windows")
3. Update the ChangeLog file for the given major version
f.e. ``ChangeLog-4.php`` from the NEWS file
f.e. ``ChangeLog-5.php`` from the NEWS file
a. go over the list and put every element on one line
@ -207,9 +211,9 @@ f.e. ``ChangeLog-4.php`` from the NEWS file
V. ``s/FR #\([0-9]\+\)/FR <?php bugl(\1); ?>/``
4. ``cp releases/4_4_0.php releases/4_4_1.php``
4. ``cp releases/5_4_0.php releases/5_4_1.php``
5. ``cvs add releases/4_4_1.php``
5. ``git add releases/5_4_1.php``
6. Update the ``releases/*.php`` file with relevant data. The release
announcement file should list in detail:
@ -232,17 +236,6 @@ to upgrade.
php-general@lists.php.net and internals@lists.php.net with a text similar to
http://news.php.net/php.internals/17222.
10. Update ``php-bugs-web/include/functions.php`` to include the new version
number, and remove the RC from there.
11. Update ``qaweb/include/release-qa.php``
- Update $QA_RELEASES with the appropriate information, which means bumping
the version number to an upcoming version.
Example: If PHP 5.3.7 is being released, then PHP 5.3.8 is the next QA version,
so replace 5.3.7 with 5.3.8 within $QA_RELEASES.
Re-releasing the same version (or -pl)
--------------------------------------

30
README.md Normal file
View File

@ -0,0 +1,30 @@
The PHP Interpreter
===================
This is the github mirror of the official PHP repository located at
http://git.php.net.
[![Build Status](https://secure.travis-ci.org/php/php-src.png?branch=master)](http://travis-ci.org/php/php-src)
Pull Requests
=============
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
mailinglist internals@lists.php.net.
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
information on the process.
Bug fixes **do not** require an RFC, but require a bugtracker ticket. Always
open a ticket at http://bugs.php.net and reference the bug id using #NNNNNN.
Fix #55371: get_magic_quotes_gpc() throws deprecation warning
After removing magic quotes, the get_magic_quotes_gpc function caused
a deprecate warning. get_magic_quotes_gpc can be used to detected
the magic_quotes behavior and therefore should not raise a warning at any
time. The patch removes this warning
We do not merge pull requests directly on github. All PRs will be
pulled and pushed through http://git.php.net.

View File

@ -21,16 +21,27 @@ PHP X.Y UPGRADE NOTES
========================================
- Drop Windows XP and 2003 support. (Pierre)
- All internal case insensitivity handling for class, function and constant
names is done according to ASCII rules, current locale settings are ignored.
- php_logo_guid(), php_egg_logo_guid(), php_real_logo_guid() and
zend_logo_guid() have been removed
- Removal of Logo GUIDs
========================================
2. New Features
========================================
- Support list in foreach. (Laruence)
(wiki.php.net/rfc/foreachlist)
- Support finally keyword. (Laruence)
(wiki.php.net/rfc/finally)
- Support constant array/string dereferencing. (Laruence)
(https://wiki.php.net/rfc/constdereference)
- Add support for using empty() on the result of function calls and
other expressions. Thus it is now possible to write empty(getArray()),
for example. (https://wiki.php.net/rfc/empty_isset_exprs)
- Added generators.
(https://wiki.php.net/rfc/generators)
========================================
2. Changes in SAPI modules
@ -63,12 +74,60 @@ PHP X.Y UPGRADE NOTES
- MessageFormatter::parse() and MessageFormat::format() (and their static
equivalents) now don't throw away better than second precision in the
arguments.
- IntlDateFormatter::__construct and datefmt_create() now accept for the
$timezone argument time zone identifiers, IntlTimeZone objects, DateTimeZone
objects and NULL. It used to accept only time zone identifiers and NULL.
Invalid time zone identifiers are no longer accepted. Emptry strings are
no longer accepted.
- The default time zone used in IntlDateFormatter::__construct and
datefmt_create() (when the corresponding argument is not passed or NULL is
passed) is now the one given by date_default_timezone_get(), not the
default ICU time zone.
- The time zone passed to the IntlDateFormatter is ignored if it is NULL and if
the calendar passed is an IntlCalendar object -- in this case, the
IntlCalendar's time zone will be used instead. Otherwise, the time zone
specified in the $timezone argument is used instead. This does not affect
old code, as IntlCalendar was introduced in this version.
- IntlDateFormatter::__construct and datefmt_create() now accept for the
$calendar argument also IntlCalendar objects.
- IntlDateFormatter::getCalendar() and datefmt_get_calendar() return false
if the IntlDateFormatter was set up with an IntlCalendar instead of the
constants IntlDateFormatter::GREGORIAN/TRADITIONAL. IntlCalendar did not
exist before this version.
- IntlDateFormatter::setCalendar() and datefmt_set_calendar() now also accept
an IntlCalendar object, in which case its time zone is taken. Passing a
constant is still allowed, and still keeps the time zone.
- IntlDateFormatter::setTimeZoneID() and datefmt_set_timezone_id() are
deprecated. Use IntlDateFormatter::setTimeZone() or datefmt_set_timezone()
instead.
- IntlDateFormatter::format() and datefmt_format() now also accept an
IntlCalendar object for formatting.
- mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb() now throw
E_DEPRECATED. Their use was already previously discouraged in the docs,
but that predated the existence of E_DEPRECATED.
- php_logo_guid(), php_egg_logo_guid(), php_real_logo_guid() and
zend_logo_guid() have been removed
- set_error_handler(NULL) can now be used to reset the error handler.
Furthermore both set_error_handler(NULL) and set_exception_handler(NULL) will
now return the previously defined error/exception handler. Previously
bool(true) was returned.
========================================
5. New Functions
========================================
- Core:
- boolval()
- Hash:
- hash_pbkdf2()
- Intl:
- datefmt_format_object()
- datefmt_get_calendar_object()
- datefmt_get_timezone()
- datefmt_set_timezone()
- datefmt_get_calendar_object()
- intlcal_create_instance()
- intlcal_get_keyword_values_for_locale()
- intlcal_get_now()
@ -140,6 +199,11 @@ PHP X.Y UPGRADE NOTES
- intltz_get_error_code()
- intltz_get_error_message()
- IntlDateFormatter::formatObject()
- IntlDateFormatter::getCalendarObject()
- IntlDateFormatter::getTimeZone()
- IntlDateFormatter::setTimeZone()
- SPL:
- SplFixedArray::__wakeup()
@ -151,6 +215,9 @@ PHP X.Y UPGRADE NOTES
- IntlCalendar
- IntlGregorianCalendar
- IntlTimeZone
- IntlBreakIterator
- IntlRuleBasedBreakIterator
- IntlCodePointBreakIterator
========================================
7. Removed Extensions
@ -179,3 +246,5 @@ PHP X.Y UPGRADE NOTES
========================================
11. Other Changes
========================================
- Logo GUIDs will no longer work

View File

@ -4,6 +4,7 @@ UPGRADE NOTES - PHP X.Y
1. Internal API changes
a. Streams pooling API
b. Lowercasing and locales
2. Build system changes
a. Unix build system changes
@ -26,6 +27,32 @@ PHPAPI int php_stream_context_set_link(php_stream_context *context,
PHPAPI int php_stream_context_del_link(php_stream_context *context,
php_stream *stream);
b. Lowercasing and locales
The lowercasing functions in zend_operators.c were split into those that do
lowercasing according to locale rules and those that do ASCII lowercasing.
ASCII:
zend_str_tolower_copy
zend_str_tolower_dup
zend_str_tolower
zend_binary_strcasecmp
zend_binary_strncasecmp
Locale-based:
zend_binary_strncasecmp_l
zend_binary_strcasecmp_l
zend_binary_zval_strcasecmp
zend_binary_zval_strncasecmp
string_compare_function_ex
string_case_compare_function
Internal engine lowercasing will be using ASCII-only rules. User-facing functions,
such as strcasecmp, will be using locale rules.
Two new functions - zend_binary_strncasecmp_l and zend_binary_strcasecmp_l - added as
locale-based counterparts to zend_binary_strcasecmp and zend_binary_strncasecmp.
========================
2. Build system changes
========================
@ -34,5 +61,5 @@ PHPAPI int php_stream_context_del_link(php_stream_context *context,
-
b. Windows build system changes
-
- Drop Windows XP and 2003 support.

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,8 @@ libZend_la_SOURCES=\
zend_objects_API.c zend_ts_hash.c zend_stream.c \
zend_default_classes.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c
zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \
zend_generators.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@

View File

@ -159,6 +159,10 @@ SOURCE=.\zend_float.c
# End Source File
# Begin Source File
SOURCE=.\zend_generators.c
# End Source File
# Begin Source File
SOURCE=.\zend_hash.c
# End Source File
# Begin Source File

View File

@ -185,6 +185,10 @@ SOURCE=.\zend_extensions.c
# End Source File
# Begin Source File
SOURCE=.\zend_generators.c
# End Source File
# Begin Source File
SOURCE=.\zend_hash.c
# End Source File
# Begin Source File

View File

@ -4,7 +4,7 @@ dnl This file contains local autoconf functions.
AC_DEFUN([LIBZEND_BISON_CHECK],[
# we only support certain bison versions
bison_version_list="1.28 1.35 1.75 1.875 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5"
bison_version_list="1.28 1.35 1.75 1.875 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5 2.5.1"
# for standalone build of Zend Engine
test -z "$SED" && SED=sed

37
Zend/tests/bug18556.phpt Normal file
View File

@ -0,0 +1,37 @@
--TEST--
Bug #18556 (Setting locale to 'tr_TR' lowercases class names)
--FILE--
<?php
$g_lang = 'tr_TR';
putenv("LANG=$g_lang");
setlocale(LC_ALL, $g_lang);
class InfoBlob {
var $foo;
function InfoBlob() {
$this->foo = "Foo";
}
}
echo "Instantiating an infoBlob with a lowercase i\n";
$foobar = new infoBlob();
echo $foobar->foo;
echo "\nInstantiating an InfoBlob with an uppercase I\n";
$foobar = new InfoBlob();
echo $foobar->foo;
echo "\n";
setlocale(LC_ALL, "tr_TR.utf8");
foreach(get_declared_classes() as $class)
{
if(!class_exists($class))
echo "$class No Longer Exists!\n";
}
echo "Done.\n";
?>
--EXPECT--
Instantiating an infoBlob with a lowercase i
Foo
Instantiating an InfoBlob with an uppercase I
Foo
Done.

View File

@ -62,17 +62,17 @@ print "\nDone\n";
?>
--EXPECTF--
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
Notice: Uninitialized string offset: 0 in %s on line %d
Notice: Uninitialized string offset: 0 in %s on line %d
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
Notice: Uninitialized string offset: %i in %s on line %d
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
Notice: Uninitialized string offset: %i in %s on line %d
@ -88,16 +88,16 @@ Notice: Uninitialized string offset: 4 in %s on line %d
Notice: Uninitialized string offset: 4 in %s on line %d
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
Notice: Uninitialized string offset: 12 in %s on line %d
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
Notice: Uninitialized string offset: 12 in %s on line %d
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
b
Done

View File

@ -13,4 +13,10 @@ function eh()
set_error_handler("eh");
$a = $empty($b);
--EXPECTF--
Warning: Uncaught exception 'Exception' with message 'error!' in %sbug51394.php:4
Stack trace:
#0 %sbug51394.php(9): eh(8, 'Undefined varia...', '%s', 9, Array)
#1 {main}
thrown in %sbug51394.php on line 4
Fatal error: Function name must be a string in %sbug51394.php on line 9

View File

@ -5,6 +5,12 @@ Bug #55509 (segfault on x86_64 using more than 2G memory)
if (PHP_INT_SIZE == 4) {
die('skip Not for 32-bits OS');
}
$zend_mm_enabled = getenv("USE_ZEND_ALLOC");
if ($zend_mm_enabled === "0") {
die("skip Zend MM disabled");
}
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
// check the available memory
if (PHP_OS == 'Linux') {

View File

@ -3,15 +3,20 @@ Bug #60738 Allow 'set_error_handler' to handle NULL
--FILE--
<?php
set_error_handler(function() { echo 'Intercepted error!', "\n"; });
var_dump(set_error_handler(
function() { echo 'Intercepted error!', "\n"; }
));
trigger_error('Error!');
set_error_handler(null);
var_dump(set_error_handler(null));
trigger_error('Error!');
?>
--EXPECTF--
NULL
Intercepted error!
object(Closure)#1 (0) {
}
Notice: Error! in %s on line %d

View File

@ -0,0 +1,23 @@
--TEST--
Bug #60738 Allow 'set_error_handler' to handle NULL
--FILE--
<?php
var_dump(set_exception_handler(
function() { echo 'Intercepted exception!', "\n"; }
));
var_dump(set_exception_handler(null));
throw new Exception('Exception!');
?>
--EXPECTF--
NULL
object(Closure)#1 (0) {
}
Fatal error: Uncaught exception 'Exception' with message 'Exception!' in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View File

@ -0,0 +1,24 @@
--TEST--
Bug #60909 (custom error handler throwing Exception + fatal error = no shutdown function).
--FILE--
<?php
register_shutdown_function(function(){echo("\n\n!!!shutdown!!!\n\n");});
set_error_handler(function($errno, $errstr, $errfile, $errline){
echo "error($errstr)";
throw new Exception("Foo");
});
require 'notfound.php';
--EXPECTF--
error(require(notfound.php): failed to open stream: No such file or directory)
Warning: Uncaught exception 'Exception' with message 'Foo' in %sbug60909_1.php:5
Stack trace:
#0 %sbug60909_1.php(8): {closure}(2, 'require(notfoun...', '%s', 8, Array)
#1 %sbug60909_1.php(8): require()
#2 {main}
thrown in %sbug60909_1.php on line 5
Fatal error: main(): Failed opening required 'notfound.php' (include_path='%s') in %sbug60909_1.php on line 8
!!!shutdown!!!

View File

@ -0,0 +1,20 @@
--TEST--
Bug #60909 (custom error handler throwing Exception + fatal error = no shutdown function).
--FILE--
<?php
register_shutdown_function(function(){echo("\n\n!!!shutdown!!!\n\n");});
set_error_handler(function($errno, $errstr, $errfile, $errline){throw new Exception("Foo");});
class Bad {
public function __toString() {
throw new Exception('Oops, I cannot do this');
}
}
$bad = new Bad();
echo "$bad";
--EXPECTF--
Fatal error: Method Bad::__toString() must not throw an exception in %sbug60909_2.php on line 0
!!!shutdown!!!

View File

@ -14,5 +14,6 @@ class B extends A
}
?>
==DONE==
--EXPECTF--
Strict Standards: Declaration of B::test() should be compatible with A::test($a) in %sbug61761.php on line %d
==DONE==

34
Zend/tests/bug61767.phpt Normal file
View File

@ -0,0 +1,34 @@
--TEST--
Bug #61767 (Shutdown functions not called in certain error situation)
--FILE--
<?php
set_error_handler(function($code, $msg, $file = null, $line = null) {
echo "Error handler called ($msg)\n";
throw new \ErrorException($msg, $code, 0, $file, $line);
});
register_shutdown_function(function(){
echo "Shutting down\n";
print_r(error_get_last());
});
//$undefined = null; // defined variable does not cause problems
$undefined->foo();
--EXPECTF--
Error handler called (Undefined variable: undefined)
Warning: Uncaught exception 'ErrorException' with message 'Undefined variable: undefined' in %sbug61767.php:13
Stack trace:
#0 %sbug61767.php(13): {closure}(8, 'Undefined varia...', '%s', 13, Array)
#1 {main}
thrown in %sbug61767.php on line 13
Fatal error: Call to a member function foo() on a non-object in %sbug61767.php on line 13
Shutting down
Array
(
[type] => 1
[message] => Call to a member function foo() on a non-object
[file] => %sbug61767.php
[line] => 13
)

32
Zend/tests/bug62358.phpt Normal file
View File

@ -0,0 +1,32 @@
--TEST--
Bug #62358 (Segfault when using traits a lot)
--SKIPIF--
<?php
if (getenv("USE_ZEND_ALLOC") !== "0") {
die("skip Need Zend MM enabled");
}
?>
--FILE--
<?php
trait T {
public function foo() {
echo "from T";
}
}
interface I {
public function foo();
}
abstract class A implements I{
use T;
}
class B extends A {
public function foo($var) {
}
}
?>
--EXPECTF--
Strict Standards: Declaration of B::foo() should be compatible with A::foo() in %sbug62358.php on line %d

33
Zend/tests/bug62653.phpt Normal file
View File

@ -0,0 +1,33 @@
--TEST--
Bug #62653: unset($array[$float]) causes a crash
--FILE--
<?php
$array = array("5"=>"bar");
$foo = "10.0000"; // gettype($foo) = "string"
$foo /= 2; //Makes $foo = 5 but still gettype($foo) = "double"
unset($array[$foo]);
print_r($array);
$array = array("5"=>"bar");
$foo = "5";
unset($array[(float)$foo]);
print_r($array);
$array = array("5"=>"bar");
$foo = "10.0000";
$foo /= 2; //Makes $foo = 5 but still gettype($foo) = "double"
$name = "foo";
unset($array[$$name]);
print_r($array);
?>
--EXPECT--
Array
(
)
Array
(
)
Array
(
)

11
Zend/tests/bug62680.phpt Normal file
View File

@ -0,0 +1,11 @@
--TEST--
Bug #62680 (Function isset() throws fatal error on set array if non-existent key depth >= 3)
--FILE--
<?php
$array = array("");
var_dump(isset($array[0]["a"]["b"]));
var_dump(isset($array[0]["a"]["b"]["c"]));
?>
--EXPECT--
bool(false)
bool(false)

23
Zend/tests/bug62763.phpt Normal file
View File

@ -0,0 +1,23 @@
--TEST--
Bug #62763 (register_shutdown_function and extending class)
--FILE--
<?php
class test1 {
public function __construct() {
register_shutdown_function(array($this, 'shutdown'));
}
public function shutdown() {
exit(__METHOD__);
}
}
class test2 extends test1 {
public function __destruct() {
exit (__METHOD__);
}
}
new test1;
new test2;
?>
--EXPECT--
test1::shutdowntest2::__destruct

21
Zend/tests/bug62892.phpt Normal file
View File

@ -0,0 +1,21 @@
--TEST--
Bug #62892 (ReflectionClass::getTraitAliases crashes on importing trait methods as private)
--FILE--
<?php
trait myTrait {
public function run() {}
}
class myClass {
use myTrait {
MyTrait::run as private;
}
}
$class = new \ReflectionClass('myClass');
var_dump($class->getTraitAliases());
?>
--EXPECTF--
array(0) {
}

22
Zend/tests/bug62907.phpt Normal file
View File

@ -0,0 +1,22 @@
--TEST--
Bug #62907 (Double free when use traits)
--FILE--
<?php
function __autoload($name) {
if ($name == "B") {
eval ("abstract class B extends A { }");
} else if ($name == "A") {
eval ("abstract class A { use T { T::__construct as __asconstruct; }}");
} else if ($name == "T") {
eval ("trait T { public function __construct() { } }");
}
return TRUE;
}
class C extends B {
public function __construct() {
}
}
echo "okey";
--EXPECT--
okey

20
Zend/tests/bug62956.phpt Normal file
View File

@ -0,0 +1,20 @@
--TEST--
Bug #62956: "incompatible" signatures for private methods should not cause E_STRICT
--FILE--
<?php
class Base
{
private function test()
{}
}
class Extension extends Base
{
private function test($arg)
{}
}
?>
==DONE==
--EXPECT--
==DONE==

50
Zend/tests/bug62991.phpt Normal file
View File

@ -0,0 +1,50 @@
--TEST--
Bug #62991 (Segfault with generator and closure)
--FILE--
<?php
function test( array $array )
{
$closure = function() use ( $array ) {
print_r( $array );
yield "hi";
};
return $closure();
}
function test2( array $array )
{
$closure = function() use ( $array ) {
print_r( $array );
yield "hi";
};
return $closure; // if you return the $closure and call it outside this function it works.
}
$generator = test(array( 1, 2, 3 ) );
foreach($generator as $something) {
}
$generator = test2(array( 1, 2, 3 ) );
foreach($generator() as $something) {
}
$generator = test2(array( 1, 2, 3 ) );
echo "okey\n";
?>
--EXPECT--
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 1
[1] => 2
[2] => 3
)
okey

36
Zend/tests/bug63111.phpt Normal file
View File

@ -0,0 +1,36 @@
--TEST--
Bug #63111 (is_callable() lies for abstract static method)
--FILE--
<?php
abstract class Foo {
abstract static function bar();
}
interface MyInterface {
static function bar();
}
abstract class Bar {
static function foo() {
echo "ok\n";
}
}
var_dump(is_callable(array("Foo", "bar")));
var_dump(is_callable("Foo::bar"));
var_dump(is_callable(array("MyInterface", "bar")));
var_dump(is_callable("MyInterface::bar"));
var_dump(is_callable(array("Bar", "foo")));
var_dump(is_callable("Bar::foo"));
Bar::foo();
Foo::bar();
?>
--EXPECTF--
Strict Standards: Static function Foo::bar() should not be abstract in %sbug63111.php on line 3
bool(false)
bool(false)
bool(false)
bool(false)
bool(true)
bool(true)
ok
Fatal error: Cannot call abstract method Foo::bar() in %sbug63111.php on line 20

12
Zend/tests/bug63173.phpt Normal file
View File

@ -0,0 +1,12 @@
--TEST--
Bug #63173: Crash when invoking invalid array callback
--FILE--
<?php
// the important part here are the indexes 1 and 2
$callback = [1 => 0, 2 => 0];
$callback();
?>
--EXPECTF--
Fatal error: Array callback has to contain indices 0 and 1 in %s on line %d

View File

@ -0,0 +1,32 @@
--TEST--
Try catch finally (basic test)
--FILE--
<?php
function foo ($throw = FALSE) {
try {
echo "try\n";
if ($throw) {
throw new Exception("ex");
}
} catch (Exception $e) {
echo "catch\n";
} finally {
echo "finally\n";
}
echo "end\n";
}
foo();
echo "\n";
foo(true);
?>
--EXPECTF--
try
finally
end
try
catch
finally
end

View File

@ -0,0 +1,21 @@
--TEST--
Try catch finally (basic test with return)
--FILE--
<?php
function foo () {
try {
echo "try\n";
return 1;
} catch (Exception $e) {
} finally {
echo "finally\n";
}
return 2;
}
var_dump(foo());
?>
--EXPECTF--
try
finally
int(1)

View File

@ -0,0 +1,40 @@
--TEST--
Try catch finally (with multi-returns)
--FILE--
<?php
function dummy($msg) {
var_dump($msg);
}
function foo ($a) {
try {
dummy("try");
return $a;
} catch (Exception $e) {
throw $e;
} finally {
dummy("finally");
return "finally";
}
return "end";
}
function &bar($a) {
try {
echo "try\n";
throw new Exception("ex");
} catch (Exception $e) {
} finally {
return $a;
}
return ($c = "end");
}
var_dump(foo("para"));
var_dump(bar("para"));
?>
--EXPECTF--
string(3) "try"
string(7) "finally"
string(7) "finally"
try
string(4) "para"

View File

@ -0,0 +1,41 @@
--TEST--
Try catch finally (nesting try-catch-finally)
--FILE--
<?php
function throw_exception($msg) {
throw new Exception($msg);
}
function foo (&$ex) {
try {
echo "1";
try {
echo "2";
throw_exception("try");
} catch (Exception $e) {
echo "3";
throw_exception("catch");
} finally {
echo "4";
throw_exception("finally");
}
} catch (Exception $e) {
$ex = $e;
echo "3";
} finally {
echo "2";
}
return 1;
}
var_dump(foo($ex));
do {
var_dump($ex->getMessage());
} while ($ex = $ex->getPrevious());
?>
--EXPECT--
123432int(1)
string(7) "finally"
string(5) "catch"

View File

@ -0,0 +1,21 @@
--TEST--
Try catch finally (with multi-returns and exception)
--FILE--
<?php
function foo ($a) {
try {
throw new Exception("ex");
} catch (PdoException $e) {
die("error");
} catch (Exception $e) {
return 2;
} finally {
return 3;
}
return 1;
}
var_dump(foo("para"));
?>
--EXPECTF--
int(3)

View File

@ -0,0 +1,28 @@
--TEST--
Try catch finally (re-throw exception in catch block)
--FILE--
<?php
function foo ($a) {
try {
throw new Exception("ex");
} catch (Exception $e) {
var_dump($a);
throw $e;
} finally {
var_dump("finally");
return "return";
}
return 1;
}
try {
var_dump(foo("para"));
} catch (Exception $e) {
"caught exception" . PHP_EOL;
var_dump($e->getMessage());
}
?>
--EXPECT--
string(4) "para"
string(7) "finally"
string(2) "ex"

View File

@ -1,12 +0,0 @@
--TEST--
errmsg: cannot create references to temp array
--FILE--
<?php
foreach (array(1,2,3) as $k=>&$v) {
}
echo "Done\n";
?>
--EXPECTF--
Fatal error: Cannot create references to elements of a temporary array expression in %s on line %d

View File

@ -0,0 +1,43 @@
--TEST--
foreach with list syntax
--FILE--
<?php
foreach(array(array(1,2), array(3,4)) as list($a, $b)) {
var_dump($a . $b);
}
$array = array(
array('a', 'b'),
array('c', 'd'),
);
foreach ($array as list($a, $b)) {
var_dump($a . $b);
}
$multi = array(
array(array(1,2), array(3,4)),
array(array(5,6), array(7,8)),
);
foreach ($multi as list(list($a, $b), list($c, $d))) {
var_dump($a . $b . $c . $d);
}
foreach ($multi as $key => list(list($a, $b), list($c, $d))) {
var_dump($key . $a . $b . $c . $d);
}
?>
--EXPECT--
string(2) "12"
string(2) "34"
string(2) "ab"
string(2) "cd"
string(4) "1234"
string(4) "5678"
string(5) "01234"
string(5) "15678"

View File

@ -0,0 +1,26 @@
--TEST--
foreach with freak lists
--FILE--
<?php
foreach (array(array(1,2), array(3,4)) as list($a, )) {
var_dump($a);
}
$array = [['a', 'b'], 'c', 'd'];
foreach($array as list(list(), $a)) {
var_dump($a);
}
?>
--EXPECTF--
int(1)
int(3)
string(1) "b"
Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d
string(0) ""
Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d
string(0) ""

View File

@ -0,0 +1,13 @@
--TEST--
foreach with list key
--FILE--
<?php
$array = [['a', 'b'], 'c', 'd'];
foreach($array as list($key) => list(list(), $a)) {
}
?>
--EXPECTF--
Fatal error: Cannot use list as key element in %sforeach_list_003.php on line %d

View File

@ -0,0 +1,13 @@
--TEST--
foreach with empty list
--FILE--
<?php
$array = [['a', 'b'], 'c', 'd'];
foreach($array as $key => list()) {
}
?>
--EXPECTF--
Fatal error: Cannot use empty list in %sforeach_list_004.php on line %d

View File

@ -0,0 +1,18 @@
--TEST--
Temporary array expressions can be iterated by reference
--FILE--
<?php
$a = 'a';
$b = 'b';
foreach ([&$a, &$b] as &$value) {
$value .= '-foo';
}
var_dump($a, $b);
?>
--EXPECT--
string(5) "a-foo"
string(5) "b-foo"

View File

@ -0,0 +1,22 @@
--TEST--
Generator keys are auto-incrementing by default
--FILE--
<?php
function gen() {
yield 'foo';
yield 'bar';
yield 5 => 'rab';
yield 'oof';
}
foreach (gen() as $k => $v) {
echo $k, ' => ', $v, "\n";
}
?>
--EXPECT--
0 => foo
1 => bar
5 => rab
6 => oof

View File

@ -0,0 +1,27 @@
--TEST--
Printing the stack trace in a generator
--FILE--
<?php
function f1() {
debug_print_backtrace();
}
function f2($arg1, $arg2) {
f1();
yield; // force generator
}
function f3($gen) {
$gen->rewind(); // trigger run
}
$gen = f2('foo', 'bar');
f3($gen);
?>
--EXPECTF--
#0 f1() called at [%s:%d]
#1 f2(foo, bar)
#2 Generator->rewind() called at [%s:%d]
#3 f3(Generator Object ()) called at [%s:%d]

View File

@ -0,0 +1,32 @@
--TEST--
Generators can be cloned
--FILE--
<?php
function firstN($end) {
for ($i = 0; $i < $end; ++$i) {
yield $i;
}
}
$g1 = firstN(5);
var_dump($g1->current());
$g1->next();
$g2 = clone $g1;
var_dump($g2->current());
$g2->next();
var_dump($g2->current());
var_dump($g1->current());
$g1->next();
var_dump($g1->current());
?>
--EXPECT--
int(0)
int(1)
int(2)
int(1)
int(2)

View File

@ -0,0 +1,33 @@
--TEST--
Cloning a generator with a foreach loop properly adds a ref for the loop var
--FILE--
<?php
function gen() {
foreach ([1, 2, 3] as $i) {
yield $i;
}
}
$g1 = gen();
var_dump($g1->current());
$g2 = clone $g1;
var_dump($g2->current());
$g1->next();
$g2->next();
var_dump($g1->current());
var_dump($g2->current());
unset($g1);
$g2->next();
var_dump($g2->current());
?>
--EXPECT--
int(1)
int(1)
int(2)
int(2)
int(3)

View File

@ -0,0 +1,18 @@
--TEST--
A generator with an active stack can be cloned
--FILE--
<?php
function gen() {
var_dump(str_repeat("x", yield));
}
$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->send(10);
?>
--EXPECT--
string(10) "xxxxxxxxxx"

View File

@ -0,0 +1,27 @@
--TEST--
A generator using a symbol table can be cloned
--FILE--
<?php
function gen() {
// force compiled variable for $foo
$foo = 'foo';
// force symbol table
extract(['foo' => 'bar']);
// interrupt
yield;
var_dump($foo);
}
$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->next();
?>
--EXPECT--
string(3) "bar"

View File

@ -0,0 +1,24 @@
--TEST--
Cloning a generator method (with $this)
--FILE--
<?php
class Test {
protected $foo;
public function gen() {
$this->foo = 'bar';
yield; // interrupt
var_dump($this->foo);
}
}
$g1 = (new Test)->gen();
$g1->rewind(); // goto yield
$g2 = clone $g1;
unset($g1);
$g2->next();
?>
--EXPECT--
string(3) "bar"

View File

@ -0,0 +1,19 @@
--TEST--
It's possible to invoke a generator dynamically
--FILE--
<?php
function gen($foo, $bar) {
yield $foo;
yield $bar;
}
$gen = call_user_func('gen', 'bar', 'foo');
foreach ($gen as $value) {
var_dump($value);
}
?>
--EXPECT--
string(3) "bar"
string(3) "foo"

View File

@ -0,0 +1,13 @@
--TEST--
Generators cannot return values (even before yield)
--FILE--
<?php
function gen() {
return $foo;
yield;
}
?>
--EXPECTF--
Fatal error: Generators cannot return values using "return" in %s on line 4

View File

@ -0,0 +1,13 @@
--TEST--
Generators cannot return values
--FILE--
<?php
function gen() {
yield;
return $abc;
}
?>
--EXPECTF--
Fatal error: Generators cannot return values using "return" in %s on line 5

View File

@ -0,0 +1,10 @@
--TEST--
The Generator class cannot be extended
--FILE--
<?php
class ExtendedGenerator extends Generator { }
?>
--EXPECTF--
Fatal error: Class ExtendedGenerator may not inherit from final class (Generator) in %s on line %d

View File

@ -0,0 +1,10 @@
--TEST--
It's not possible to directly instantiate the Generator class
--FILE--
<?php
new Generator;
?>
--EXPECTF--
Catchable fatal error: The "Generator" class is reserved for internal use and cannot be manually instantiated in %s on line %d

View File

@ -0,0 +1,18 @@
--TEST--
Non-ref generators cannot be iterated by-ref
--FILE--
<?php
function gen() { yield; }
$gen = gen();
foreach ($gen as &$value) { }
?>
--EXPECTF--
Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d
Stack trace:
#0 %s(%d): unknown()
#1 {main}
thrown in %s on line %d

View File

@ -0,0 +1,17 @@
--TEST--
It is not possible to resume an already running generator
--FILE--
<?php
function gen() {
$gen = yield;
$gen->next();
}
$gen = gen();
$gen->send($gen);
$gen->next();
?>
--EXPECTF--
Fatal error: Cannot resume an already running generator in %s on line %d

View File

@ -0,0 +1,46 @@
--TEST--
Generators can't be serialized or unserialized
--FILE--
<?php
function gen() { yield; }
$gen = gen();
try {
serialize($gen);
} catch (Exception $e) {
echo $e, "\n\n";
}
try {
var_dump(unserialize('O:9:"Generator":0:{}'));
} catch (Exception $e) {
echo $e, "\n\n";
}
try {
var_dump(unserialize('C:9:"Generator":0:{}'));
} catch (Exception $e) {
echo $e;
}
?>
--EXPECTF--
exception 'Exception' with message 'Serialization of 'Generator' is not allowed' in %s:%d
Stack trace:
#0 %s(%d): serialize(Object(Generator))
#1 {main}
exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d
Stack trace:
#0 [internal function]: Generator->__wakeup()
#1 %s(%d): unserialize('O:9:"Generator"...')
#2 {main}
Notice: unserialize(): Error at offset 19 of 20 bytes in %s on line %d
exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d
Stack trace:
#0 %s(%d): unserialize('C:9:"Generator"...')
#1 {main}

View File

@ -0,0 +1,16 @@
--TEST--
A notice is thrown when yielding a constant value by reference
--FILE--
<?php
function &gen() {
yield "foo";
}
$gen = gen();
var_dump($gen->current());
?>
--EXPECTF--
Notice: Only variable references should be yielded by reference in %s on line %d
string(3) "foo"

View File

@ -0,0 +1,29 @@
--TEST--
yield cannot be used in a finally block when the generator is force-closed
--FILE--
<?php
function gen() {
try {
echo "before yield\n";
yield;
echo "after yield\n";
} finally {
echo "before yield in finally\n";
yield;
echo "after yield in finally\n";
}
echo "after finally\n";
}
$gen = gen();
$gen->rewind();
unset($gen);
?>
--EXPECTF--
before yield
before yield in finally
Fatal error: Cannot yield from finally in a force-closed generator in %s on line %d

View File

@ -0,0 +1,20 @@
--TEST--
Yielding the result of a non-ref function call throw a notice
--FILE--
<?php
function foo() {
return "bar";
}
function &gen() {
yield foo();
}
$gen = gen();
var_dump($gen->current());
?>
--EXPECTF--
Notice: Only variable references should be yielded by reference in %s on line %d
string(3) "bar"

View File

@ -0,0 +1,10 @@
--TEST--
Yield cannot be used outside of functions
--FILE--
<?php
yield "Test";
?>
--EXPECTF--
Fatal error: The "yield" expression can only be used inside a function in %s on line %d

View File

@ -0,0 +1,36 @@
--TEST--
Creating an infinite fibonacci list using a generator
--FILE--
<?php
function fib() {
list($a, $b) = [1, 1];
while (true) {
yield $b;
list($a, $b) = [$b, $a + $b];
}
}
foreach (fib() as $n) {
if ($n > 1000) break;
var_dump($n);
}
?>
--EXPECT--
int(1)
int(2)
int(3)
int(5)
int(8)
int(13)
int(21)
int(34)
int(55)
int(89)
int(144)
int(233)
int(377)
int(610)
int(987)

View File

@ -0,0 +1,25 @@
--TEST--
finally is run even if a generator is closed mid-execution
--FILE--
<?php
function gen() {
try {
echo "before yield\n";
yield;
echo "after yield\n";
} finally {
echo "finally run\n";
}
echo "code after finally\n";
}
$gen = gen();
$gen->rewind();
unset($gen);
?>
--EXPECT--
before yield
finally run

View File

@ -0,0 +1,28 @@
--TEST--
Use of finally in generator without interrupt
--FILE--
<?php
function gen() {
try {
throw new Exception;
} finally {
echo "finally run\n";
}
yield; // force generator
}
$gen = gen();
$gen->rewind(); // force run
?>
--EXPECTF--
finally run
Fatal error: Uncaught exception 'Exception' in %s:%d
Stack trace:
#0 [internal function]: gen()
#1 %s(%d): Generator->rewind()
#2 {main}
thrown in %s on line %d

View File

@ -0,0 +1,33 @@
--TEST--
Use of finally in generator with return
--FILE--
<?php
function gen() {
try {
try {
echo "before return\n";
return;
echo "after return\n";
} finally {
echo "before return in inner finally\n";
return;
echo "after return in inner finally\n";
}
} finally {
echo "outer finally run\n";
}
echo "code after finally\n";
yield; // force generator
}
$gen = gen();
$gen->rewind(); // force run
?>
--EXPECTF--
before return
before return in inner finally
outer finally run

View File

@ -0,0 +1,21 @@
--TEST--
func_get_args() can be used inside generator functions
--FILE--
<?php
function gen() {
var_dump(func_get_args());
yield; // trigger generator
}
$gen = gen("foo", "bar");
$gen->rewind();
?>
--EXPECT--
array(2) {
[0]=>
string(3) "foo"
[1]=>
string(3) "bar"
}

View File

@ -0,0 +1,20 @@
--TEST--
Closures can be generators
--FILE--
<?php
$genFactory = function() {
yield 1;
yield 2;
yield 3;
};
foreach ($genFactory() as $value) {
var_dump($value);
}
?>
--EXPECT--
int(1)
int(2)
int(3)

View File

@ -0,0 +1,20 @@
--TEST--
Non-static closures can be generators
--FILE--
<?php
class Test {
public function getGenFactory() {
return function() {
yield $this;
};
}
}
$genFactory = (new Test)->getGenFactory();
var_dump($genFactory()->current());
?>
--EXPECT--
object(Test)#1 (0) {
}

View File

@ -0,0 +1,37 @@
--TEST--
Generators work properly in MultipleIterator
--FILE--
<?php
function gen1() {
yield 'a';
yield 'aa';
}
function gen2() {
yield 'b';
yield 'bb';
}
$it = new MultipleIterator;
$it->attachIterator(gen1());
$it->attachIterator(gen2());
foreach ($it as $values) {
var_dump($values);
}
?>
--EXPECT--
array(2) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
}
array(2) {
[0]=>
string(2) "aa"
[1]=>
string(2) "bb"
}

View File

@ -0,0 +1,29 @@
--TEST--
Methods can be generators
--FILE--
<?php
class Test implements IteratorAggregate {
protected $data;
public function __construct(array $data) {
$this->data = $data;
}
public function getIterator() {
foreach ($this->data as $value) {
yield $value;
}
}
}
$test = new Test(['foo', 'bar', 'baz']);
foreach ($test as $value) {
var_dump($value);
}
?>
--EXPECT--
string(3) "foo"
string(3) "bar"
string(3) "baz"

View File

@ -0,0 +1,44 @@
--TEST--
Generator methods can yield by reference
--FILE--
<?php
class Test implements IteratorAggregate {
protected $data;
public function __construct(array $data) {
$this->data = $data;
}
public function getData() {
return $this->data;
}
public function &getIterator() {
foreach ($this->data as $key => &$value) {
yield $key => $value;
}
}
}
$test = new Test([1, 2, 3, 4, 5]);
foreach ($test as &$value) {
$value *= -1;
}
var_dump($test->getData());
?>
--EXPECT--
array(5) {
[0]=>
int(-1)
[1]=>
int(-2)
[2]=>
int(-3)
[3]=>
int(-4)
[4]=>
&int(-5)
}

View File

@ -0,0 +1,18 @@
--TEST--
A generator function returns a Generator object
--FILE--
<?php
function gen() {
// execution is suspended here, so the following never gets run:
echo "Foo";
// trigger a generator
yield;
}
$generator = gen();
var_dump($generator instanceof Generator);
?>
--EXPECT--
bool(true)

View File

@ -0,0 +1,62 @@
--TEST--
A generator can only be rewinded before or at the first yield
--FILE--
<?php
function gen() {
echo "before yield\n";
yield;
echo "after yield\n";
yield;
}
$gen = gen();
$gen->rewind();
$gen->rewind();
$gen->next();
try {
$gen->rewind();
} catch (Exception $e) {
echo "\n", $e, "\n\n";
}
function &gen2() {
$foo = 'bar';
yield $foo;
yield $foo;
}
$gen = gen2();
foreach ($gen as $v) { }
try {
foreach ($gen as $v) { }
} catch (Exception $e) {
echo $e, "\n\n";
}
function gen3() {
echo "in generator\n";
if (false) yield;
}
$gen = gen3();
$gen->rewind();
?>
--EXPECTF--
before yield
after yield
exception 'Exception' with message 'Cannot rewind a generator that was already run' in %s:%d
Stack trace:
#0 %s(%d): Generator->rewind()
#1 {main}
exception 'Exception' with message 'Cannot traverse an already closed generator' in %s:%d
Stack trace:
#0 %s(%d): unknown()
#1 {main}
in generator

View File

@ -0,0 +1,22 @@
--TEST--
Values can be sent back to the generator
--FILE--
<?php
function gen() {
var_dump(yield "yield foo");
var_dump(yield "yield bar");
}
$gen = gen();
var_dump($gen->current());
$gen->send("send bar");
var_dump($gen->current());
$gen->send("send foo");
?>
--EXPECT--
string(9) "yield foo"
string(8) "send bar"
string(9) "yield bar"
string(8) "send foo"

View File

@ -0,0 +1,29 @@
--TEST--
A static method can be a generator
--FILE--
<?php
class Test {
public static function gen() {
var_dump(get_class());
var_dump(get_called_class());
yield 1;
yield 2;
yield 3;
}
}
class ExtendedTest extends Test {
}
foreach (ExtendedTest::gen() as $i) {
var_dump($i);
}
?>
--EXPECT--
string(4) "Test"
string(12) "ExtendedTest"
int(1)
int(2)
int(3)

View File

@ -0,0 +1,32 @@
--TEST--
Stack is cleaned up properly when an exception is thrown during a function call
--FILE--
<?php
function throwException() {
throw new Exception('test');
}
function gen() {
yield 'foo';
strlen("foo", "bar", throwException());
yield 'bar';
}
$gen = gen();
var_dump($gen->current());
try {
$gen->next();
} catch (Exception $e) {
echo 'Caught exception with message "', $e->getMessage(), '"', "\n";
}
var_dump($gen->current());
?>
--EXPECT--
string(3) "foo"
Caught exception with message "test"
NULL

View File

@ -0,0 +1,28 @@
--TEST--
Generators can throw exceptions
--FILE--
<?php
function gen() {
yield 'foo';
throw new Exception('test');
yield 'bar';
}
$gen = gen();
var_dump($gen->current());
try {
$gen->next();
} catch (Exception $e) {
echo 'Caught exception with message "', $e->getMessage(), '"', "\n";
}
var_dump($gen->current());
?>
--EXPECT--
string(3) "foo"
Caught exception with message "test"
NULL

View File

@ -0,0 +1,20 @@
--TEST--
Exceptions throwing by generators during foreach iteration are properly handled
--FILE--
<?php
function gen() {
throw new Exception("foo");
yield; // force generator
}
foreach (gen() as $value) { }
?>
--EXPECTF--
Fatal error: Uncaught exception 'Exception' with message 'foo' in %s:%d
Stack trace:
#0 %s(%d): gen()
#1 {main}
thrown in %s on line %d

View File

@ -0,0 +1,26 @@
--TEST--
Generators can also yield keys
--FILE--
<?php
function reverse(array $array) {
end($array);
while (null !== $key = key($array)) {
yield $key => current($array);
prev($array);
}
}
$array = [
'foo' => 'bar',
'bar' => 'foo',
];
foreach (reverse($array) as $key => $value) {
echo $key, ' => ', $value, "\n";
}
?>
--EXPECT--
bar => foo
foo => bar

View File

@ -0,0 +1,39 @@
--TEST--
Yield can be used in nested method calls
--FILE--
<?php
class A {
function foo() {
echo "Called A::foo\n";
}
}
class B {
function foo() {
echo "Called B::foo\n";
}
}
function gen($obj) {
$obj->foo($obj->foo(yield));
}
$g1 = gen(new A);
$g1->current();
$g2 = gen(new B);
$g2->current();
$g1->next();
$g3 = clone $g2;
unset($g2);
$g3->next();
?>
--EXPECT--
Called A::foo
Called A::foo
Called B::foo
Called B::foo

View File

@ -0,0 +1,19 @@
--TEST--
foreach() (and other) variables aren't leaked on premature close
--FILE--
<?php
function gen(array $array) {
foreach ($array as $value) {
yield $value;
}
}
$gen = gen(['Foo', 'Bar']);
var_dump($gen->current());
// generator is closed here, without running SWITCH_FREE
?>
--EXPECT--
string(3) "Foo"

View File

@ -0,0 +1,14 @@
--TEST--
Calls to send() after close should do nothing
--FILE--
<?php
function gen() { var_dump(yield); }
$gen = gen();
$gen->send('foo');
$gen->send('bar');
?>
--EXPECT--
string(3) "foo"

View File

@ -0,0 +1,20 @@
--TEST--
$generator->send() returns the yielded value
--FILE--
<?php
function reverseEchoGenerator() {
$data = yield;
while (true) {
$data = (yield strrev($data));
}
}
$gen = reverseEchoGenerator();
var_dump($gen->send('foo'));
var_dump($gen->send('bar'));
?>
--EXPECT--
string(3) "oof"
string(3) "rab"

View File

@ -0,0 +1,13 @@
--TEST--
There shouldn't be any leaks when the genertor's return value isn't used
--FILE--
<?php
function gen($foo) { yield; }
gen('foo'); // return value not used
?>
===DONE===
--EXPECT--
===DONE===

View File

@ -0,0 +1,23 @@
--TEST--
Simple generator xrange() test
--FILE--
<?php
function xrange($start, $end, $step = 1) {
for ($i = $start; $i <= $end; $i += $step) {
yield $i;
}
}
foreach (xrange(10, 20, 2) as $i) {
var_dump($i);
}
?>
--EXPECT--
int(10)
int(12)
int(14)
int(16)
int(18)
int(20)

View File

@ -0,0 +1,18 @@
--TEST--
Array keys can be yielded from generators
--FILE--
<?php
function gen() {
yield [] => 1;
}
$gen = gen();
var_dump($gen->key());
var_dump($gen->current());
?>
--EXPECT--
array(0) {
}
int(1)

View File

@ -0,0 +1,26 @@
--TEST--
Array offsets can be yielded by reference
--FILE--
<?php
function &gen(array &$array) {
yield $array[0];
}
$array = [1, 2, 3];
$gen = gen($array);
foreach ($gen as &$val) {
$val *= -1;
}
var_dump($array);
?>
--EXPECT--
array(3) {
[0]=>
&int(-1)
[1]=>
int(2)
[2]=>
int(3)
}

View File

@ -0,0 +1,42 @@
--TEST--
Generators can yield by-reference
--FILE--
<?php
function &iter(array &$array) {
foreach ($array as $key => &$value) {
yield $key => $value;
}
}
$array = [1, 2, 3];
$iter = iter($array);
foreach ($iter as &$value) {
$value *= -1;
}
var_dump($array);
$array = [1, 2, 3];
foreach (iter($array) as &$value) {
$value *= -1;
}
var_dump($array);
?>
--EXPECT--
array(3) {
[0]=>
int(-1)
[1]=>
int(-2)
[2]=>
&int(-3)
}
array(3) {
[0]=>
int(-1)
[1]=>
int(-2)
[2]=>
&int(-3)
}

View File

@ -0,0 +1,15 @@
--TEST--
"yield" can occur during a function call
--FILE--
<?php
function gen() {
var_dump(str_repeat("x", yield));
}
$gen = gen();
$gen->send(10);
?>
--EXPECT--
string(10) "xxxxxxxxxx"

View File

@ -0,0 +1,35 @@
--TEST--
Yield can be used during a method call
--FILE--
<?php
class A {
public function b($c) {
echo $c, "\n";
}
}
function gen() {
$a = new A;
$a->b(yield);
}
$gen = gen();
$gen->send('foo');
// test resource cleanup
$gen = gen();
$gen->rewind();
unset($gen);
// test cloning
$g1 = gen();
$g1->rewind();
$g2 = clone $g1;
unset($g1);
$g2->send('bar');
?>
--EXPECT--
foo
bar

View File

@ -0,0 +1,29 @@
--TEST--
yield can be used in finally (apart from forced closes)
--FILE--
<?php
function gen() {
try {
echo "before return\n";
return;
echo "after return\n";
} finally {
echo "before yield\n";
yield "yielded value";
echo "after yield\n";
}
echo "after finally\n";
}
$gen = gen();
var_dump($gen->current());
$gen->next();
?>
--EXPECTF--
before return
before yield
string(%d) "yielded value"
after yield

View File

@ -0,0 +1,23 @@
--TEST--
No additional parenthesis are required around yield if they are already present
--FILE--
<?php
function gen() {
if (yield $foo); elseif (yield $foo);
if (yield $foo): elseif (yield $foo): endif;
while (yield $foo);
do {} while (yield $foo);
switch (yield $foo) {}
(yield $foo);
die(yield $foo);
func(yield $foo);
$foo->func(yield $foo);
new Foo(yield $foo);
}
echo "Done";
?>
--EXPECT--
Done

View File

@ -0,0 +1,24 @@
--TEST--
The result of a by-ref function call can be yielded just fine
--FILE--
<?php
function &nop(&$var) {
return $var;
}
function &gen(&$var) {
yield nop($var);
}
$var = "foo";
$gen = gen($var);
foreach ($gen as &$varRef) {
$varRef = "bar";
}
var_dump($var);
?>
--EXPECT--
string(3) "bar"

View File

@ -0,0 +1,27 @@
--TEST--
yield can be used without a value
--FILE--
<?php
function recv() {
while (true) {
var_dump(yield);
}
}
$reciever = recv();
var_dump($reciever->current());
$reciever->send(1);
var_dump($reciever->current());
$reciever->send(2);
var_dump($reciever->current());
$reciever->send(3);
?>
--EXPECT--
NULL
int(1)
NULL
int(2)
NULL
int(3)

View File

@ -30,10 +30,10 @@ echo "Done\n";
--EXPECTF--
string(1) "i"
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
string(1) "S"
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
string(1) "S"
Warning: Illegal string offset 'run away' in %s on line %d
@ -46,10 +46,10 @@ string(1) "o"
Notice: A non well formed numeric value encountered in %s on line %d
string(1) "r"
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
string(1) "i"
Notice: String offset cast occured in %s on line %d
Notice: String offset cast occurred in %s on line %d
string(1) "S"
Warning: Illegal offset type in %s on line %d

View File

@ -0,0 +1,36 @@
--TEST--
Try catch finally
--FILE--
<?php
class AE extends Exception {};
class BE extends Exception {};
function foo () {
try {
try {
try {
throw new Exception("try");
} catch (AE $e) {
echo "0";
die("error");
} finally {
echo "1";
}
} finally {
echo "2";
}
} catch (BE $e) {
die("error");
} catch (Exception $e) {
echo "3";
} finally {
echo "4";
}
return 1;
}
var_dump(foo());
?>
--EXPECTF--
1234int(1)

Some files were not shown because too many files have changed in this diff Show More