mirror of
https://github.com/php/php-src.git
synced 2024-10-02 07:16:11 +00:00
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:
commit
ca6273240e
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
24
.travis.yml
Normal 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"
|
@ -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
202
INSTALL
@ -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
34
NEWS
@ -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! >>>
|
||||
|
@ -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
30
README.md
Normal 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.
|
69
UPGRADING
69
UPGRADING
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
22097
Zend/ChangeLog
22097
Zend/ChangeLog
File diff suppressed because it is too large
Load Diff
@ -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@
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
37
Zend/tests/bug18556.phpt
Normal 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.
|
@ -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
|
||||
|
@ -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
|
@ -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') {
|
||||
|
@ -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
|
||||
|
23
Zend/tests/bug60738_variation.phpt
Normal file
23
Zend/tests/bug60738_variation.phpt
Normal 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
|
||||
|
24
Zend/tests/bug60909_1.phpt
Normal file
24
Zend/tests/bug60909_1.phpt
Normal 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!!!
|
20
Zend/tests/bug60909_2.phpt
Normal file
20
Zend/tests/bug60909_2.phpt
Normal 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!!!
|
@ -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
34
Zend/tests/bug61767.phpt
Normal 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
32
Zend/tests/bug62358.phpt
Normal 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
33
Zend/tests/bug62653.phpt
Normal 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
11
Zend/tests/bug62680.phpt
Normal 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
23
Zend/tests/bug62763.phpt
Normal 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
21
Zend/tests/bug62892.phpt
Normal 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
22
Zend/tests/bug62907.phpt
Normal 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
20
Zend/tests/bug62956.phpt
Normal 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
50
Zend/tests/bug62991.phpt
Normal 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
36
Zend/tests/bug63111.phpt
Normal 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
12
Zend/tests/bug63173.phpt
Normal 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
|
32
Zend/tests/catch_finally_001.phpt
Normal file
32
Zend/tests/catch_finally_001.phpt
Normal 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
|
21
Zend/tests/catch_finally_002.phpt
Normal file
21
Zend/tests/catch_finally_002.phpt
Normal 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)
|
40
Zend/tests/catch_finally_003.phpt
Normal file
40
Zend/tests/catch_finally_003.phpt
Normal 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"
|
41
Zend/tests/catch_finally_004.phpt
Normal file
41
Zend/tests/catch_finally_004.phpt
Normal 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"
|
21
Zend/tests/catch_finally_005.phpt
Normal file
21
Zend/tests/catch_finally_005.phpt
Normal 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)
|
28
Zend/tests/catch_finally_006.phpt
Normal file
28
Zend/tests/catch_finally_006.phpt
Normal 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"
|
@ -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
|
43
Zend/tests/foreach_list_001.phpt
Normal file
43
Zend/tests/foreach_list_001.phpt
Normal 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"
|
26
Zend/tests/foreach_list_002.phpt
Normal file
26
Zend/tests/foreach_list_002.phpt
Normal 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) ""
|
13
Zend/tests/foreach_list_003.phpt
Normal file
13
Zend/tests/foreach_list_003.phpt
Normal 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
|
13
Zend/tests/foreach_list_004.phpt
Normal file
13
Zend/tests/foreach_list_004.phpt
Normal 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
|
18
Zend/tests/foreach_temp_array_expr_with_refs.phpt
Normal file
18
Zend/tests/foreach_temp_array_expr_with_refs.phpt
Normal 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"
|
22
Zend/tests/generators/auto_incrementing_keys.phpt
Normal file
22
Zend/tests/generators/auto_incrementing_keys.phpt
Normal 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
|
27
Zend/tests/generators/backtrace.phpt
Normal file
27
Zend/tests/generators/backtrace.phpt
Normal 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]
|
32
Zend/tests/generators/clone.phpt
Normal file
32
Zend/tests/generators/clone.phpt
Normal 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)
|
33
Zend/tests/generators/clone_with_foreach.phpt
Normal file
33
Zend/tests/generators/clone_with_foreach.phpt
Normal 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)
|
18
Zend/tests/generators/clone_with_stack.phpt
Normal file
18
Zend/tests/generators/clone_with_stack.phpt
Normal 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"
|
27
Zend/tests/generators/clone_with_symbol_table.phpt
Normal file
27
Zend/tests/generators/clone_with_symbol_table.phpt
Normal 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"
|
24
Zend/tests/generators/clone_with_this.phpt
Normal file
24
Zend/tests/generators/clone_with_this.phpt
Normal 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"
|
19
Zend/tests/generators/dynamic_call.phpt
Normal file
19
Zend/tests/generators/dynamic_call.phpt
Normal 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"
|
@ -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
|
@ -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
|
10
Zend/tests/generators/errors/generator_extend_error.phpt
Normal file
10
Zend/tests/generators/errors/generator_extend_error.phpt
Normal 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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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}
|
16
Zend/tests/generators/errors/yield_const_by_ref_error.phpt
Normal file
16
Zend/tests/generators/errors/yield_const_by_ref_error.phpt
Normal 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"
|
@ -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
|
@ -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"
|
@ -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
|
36
Zend/tests/generators/fibonacci.phpt
Normal file
36
Zend/tests/generators/fibonacci.phpt
Normal 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)
|
25
Zend/tests/generators/finally_ran_on_close.phpt
Normal file
25
Zend/tests/generators/finally_ran_on_close.phpt
Normal 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
|
28
Zend/tests/generators/finally_uninterrupted.phpt
Normal file
28
Zend/tests/generators/finally_uninterrupted.phpt
Normal 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
|
33
Zend/tests/generators/finally_with_return.phpt
Normal file
33
Zend/tests/generators/finally_with_return.phpt
Normal 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
|
21
Zend/tests/generators/func_get_args.phpt
Normal file
21
Zend/tests/generators/func_get_args.phpt
Normal 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"
|
||||
}
|
20
Zend/tests/generators/generator_closure.phpt
Normal file
20
Zend/tests/generators/generator_closure.phpt
Normal 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)
|
20
Zend/tests/generators/generator_closure_with_this.phpt
Normal file
20
Zend/tests/generators/generator_closure_with_this.phpt
Normal 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) {
|
||||
}
|
37
Zend/tests/generators/generator_in_multipleiterator.phpt
Normal file
37
Zend/tests/generators/generator_in_multipleiterator.phpt
Normal 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"
|
||||
}
|
29
Zend/tests/generators/generator_method.phpt
Normal file
29
Zend/tests/generators/generator_method.phpt
Normal 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"
|
44
Zend/tests/generators/generator_method_by_ref.phpt
Normal file
44
Zend/tests/generators/generator_method_by_ref.phpt
Normal 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)
|
||||
}
|
18
Zend/tests/generators/generator_returns_generator.phpt
Normal file
18
Zend/tests/generators/generator_returns_generator.phpt
Normal 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)
|
62
Zend/tests/generators/generator_rewind.phpt
Normal file
62
Zend/tests/generators/generator_rewind.phpt
Normal 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
|
22
Zend/tests/generators/generator_send.phpt
Normal file
22
Zend/tests/generators/generator_send.phpt
Normal 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"
|
29
Zend/tests/generators/generator_static_method.phpt
Normal file
29
Zend/tests/generators/generator_static_method.phpt
Normal 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)
|
@ -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
|
28
Zend/tests/generators/generator_throwing_exception.phpt
Normal file
28
Zend/tests/generators/generator_throwing_exception.phpt
Normal 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
|
20
Zend/tests/generators/generator_throwing_in_foreach.phpt
Normal file
20
Zend/tests/generators/generator_throwing_in_foreach.phpt
Normal 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
|
||||
|
26
Zend/tests/generators/generator_with_keys.phpt
Normal file
26
Zend/tests/generators/generator_with_keys.phpt
Normal 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
|
39
Zend/tests/generators/nested_method_calls.phpt
Normal file
39
Zend/tests/generators/nested_method_calls.phpt
Normal 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
|
19
Zend/tests/generators/no_foreach_var_leaks.phpt
Normal file
19
Zend/tests/generators/no_foreach_var_leaks.phpt
Normal 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"
|
14
Zend/tests/generators/send_after_close.phpt
Normal file
14
Zend/tests/generators/send_after_close.phpt
Normal 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"
|
20
Zend/tests/generators/send_returns_current.phpt
Normal file
20
Zend/tests/generators/send_returns_current.phpt
Normal 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"
|
13
Zend/tests/generators/unused_return_value.phpt
Normal file
13
Zend/tests/generators/unused_return_value.phpt
Normal 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===
|
23
Zend/tests/generators/xrange.phpt
Normal file
23
Zend/tests/generators/xrange.phpt
Normal 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)
|
18
Zend/tests/generators/yield_array_key.phpt
Normal file
18
Zend/tests/generators/yield_array_key.phpt
Normal 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)
|
26
Zend/tests/generators/yield_array_offset_by_ref.phpt
Normal file
26
Zend/tests/generators/yield_array_offset_by_ref.phpt
Normal 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)
|
||||
}
|
42
Zend/tests/generators/yield_by_reference.phpt
Normal file
42
Zend/tests/generators/yield_by_reference.phpt
Normal 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)
|
||||
}
|
15
Zend/tests/generators/yield_during_function_call.phpt
Normal file
15
Zend/tests/generators/yield_during_function_call.phpt
Normal 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"
|
35
Zend/tests/generators/yield_during_method_call.phpt
Normal file
35
Zend/tests/generators/yield_during_method_call.phpt
Normal 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
|
29
Zend/tests/generators/yield_in_finally.phpt
Normal file
29
Zend/tests/generators/yield_in_finally.phpt
Normal 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
|
23
Zend/tests/generators/yield_in_parenthesis.phpt
Normal file
23
Zend/tests/generators/yield_in_parenthesis.phpt
Normal 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
|
@ -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"
|
27
Zend/tests/generators/yield_without_value.phpt
Normal file
27
Zend/tests/generators/yield_without_value.phpt
Normal 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)
|
@ -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
|
||||
|
36
Zend/tests/try_catch_finally_001.phpt
Normal file
36
Zend/tests/try_catch_finally_001.phpt
Normal 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
Loading…
Reference in New Issue
Block a user