summaryrefslogtreecommitdiff
path: root/UPGRADING
diff options
context:
space:
mode:
Diffstat (limited to 'UPGRADING')
-rw-r--r--UPGRADING555
1 files changed, 162 insertions, 393 deletions
diff --git a/UPGRADING b/UPGRADING
index ba0d5b4ed5..657aab9504 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -1,4 +1,4 @@
-PHP 7.4 UPGRADE NOTES
+PHP 8.0 UPGRADE NOTES
1. Backward Incompatible Changes
2. New Features
@@ -12,9 +12,8 @@ PHP 7.4 UPGRADE NOTES
10. New Global Constants
11. Changes to INI File Handling
12. Windows Support
-13. Migration to pkg-config
-14. Other Changes
-15. Performance Improvements
+13. Other Changes
+14. Performance Improvements
========================================
@@ -22,171 +21,187 @@ PHP 7.4 UPGRADE NOTES
========================================
- Core:
- . get_declared_classes() no longer returns anonymous classes that haven't
- been instantiated yet.
-
-- Curl:
- . Attempting to serialize a CURLFile class will now generate an exception.
- Previously the exception was only thrown on unserialization.
-
-- Date:
- . Calling var_dump() or similar on a DateTime(Immutable) instance will no
- longer leave behind accessible properties on the object.
- . Comparison of DateInterval objects (using ==, < and so on) will now generate
- a warning and always return false. Previously all DateInterval objects were
- considered equal, unless they had properties.
-
-- Intl:
- . The default parameter value of idn_to_ascii() and idn_to_utf8() is now
- INTL_IDNA_VARIANT_UTS46 instead of the deprecated INTL_IDNA_VARIANT_2003.
-
-- MySQLi:
- . The embedded server functionality has been removed. It was broken since
- at least PHP 7.0.
-
-- Openssl:
- . The openssl_random_pseudo_bytes() function will now throw an exception in
- error situations, similar to random_bytes(). In particular, an Error is
- thrown if the number of requested bytes is smaller *or equal* than zero,
- and an Exception is thrown is sufficient randomness cannot be gathered.
- The $crypto_strong output argument is guaranteed to always be true if the
- function does not throw, so explicitly checking it is not necessary.
- RFC: http://php.net/manual/de/function.openssl-random-pseudo-bytes.php
-
-- PCRE:
- . When PREG_UNMATCHED_AS_NULL mode is used, trailing unmatched capturing
- groups will now also be set to null (or [null, -1] if offset capture is
- enabled). This means that the size of the $matches will always be the same.
-
-- PEAR:
- . Installation of PEAR (including PECL) is no longer enabled by default. It
- can be explicitly enabled using --with-pear. This option is deprecated and
- may be removed in the future.
+ . Methods with the same name as the class are no longer interpreted as
+ constructors. The __construct() method should be used instead.
+ . Removed ability to call non-static methods statically.
+ . Removed (unset) cast.
+ . Removed track_errors ini directive. This means that $php_errormsg is no
+ longer available. The error_get_last() function may be used instead.
+ . Removed the ability to define case-insensitive constants. The third
+ argument to define() may no longer be true.
+ . Access to undefined constants now always results in an Error exception.
+ Previously, unqualified constant accesses resulted in a warning and were
+ interpreted as strings.
+ . Removed ability to specify an autoloader using an __autoload() function.
+ spl_autoload_register() should be used instead.
+ . Removed the $errcontext argument for custom error handlers.
+ . Removed create_function(). Anonymous functions may be used instead.
+ . Removed each(). foreach or ArrayIterator should be used instead.
+ . Removed ability to unbind $this from closures that were created from a
+ method, using Closure::fromCallable() or ReflectionMethod::getClosure().
+ . Any array that has a number n as its first numeric key will use n+1 for
+ its next implicit key. Even if n is negative.
+ RFC: https://wiki.php.net/rfc/negative_array_index
+ . The @ operator will no longer silence fatal errors (E_ERROR, E_CORE_ERROR,
+ E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR, E_PARSE). Error handlers
+ that expect error_reporting to be 0 when @ is used, should be adjusted to
+ use a mask check instead:
+
+ // Replace
+ function my_error_handler($err_no, $err_msg, $filename, $linenum) {
+ if (error_reporting() == 0) {
+ return; // Silenced
+ }
+ // ...
+ }
-- PDO:
- . Attempting to serialize a PDO or PDOStatement instance will now generate
- an Exception rather than a PDOException, consistent with other internal
- classes which do not support serialization.
+ // With
+ function my_error_handler($err_no, $err_msg, $filename, $linenum) {
+ if (!(error_reporting() & $err_no)) {
+ return; // Silenced
+ }
+ // ...
+ }
-- Reflection:
- . Reflection objects will now generate an exception if an attempt is made
- to serialize them. Serialization for reflection objects was never
- supported and resulted in corrupted reflection objects. It has been
- explicitly prohibited now.
+ Additionally, care should be taken that error messages are not displayed in
+ production environments, which can result in information leaks. Please
+ ensure that display_errors=Off is used in conjunction with error logging.
-- SPL:
- . Calling get_object_vars() on an ArrayObject instance will now always return
- the properties of the ArrayObject itself (or a subclass). Previously it
- returned the values of the wrapped array/object unless the STD_PROP_LIST
- flag was specified. Other affected operations are:
-
- * ReflectionObject::getProperties()
- * reset(), current(), etc. Use Iterator methods instead.
- * Potentially others working on object properties as a list.
-
- (array) casts are *not* affected. They will continue to return either the
- wrapped array, or the ArrayObject properties, depending on whether the
- STD_PROP_LIST flag is used.
- . SplPriorityQueue::setExtractFlags() will throw an exception if zero is
- passed. Previously this would generate a recoverable fatal error on the
- next extraction operation.
- . ArrayObject, ArrayIterator, SplDoublyLinkedList and SplObjectStorage now
- support the __serialize() + __unserialize() mechanism in addition to the
- Serializable interface. This means that serialization payloads created on
- older PHP versions can still be unserialized, but new payloads created by
- PHP 7.4 will not be understood by older versions.
+- COM:
+ . Removed the ability to import case-insensitive constants from type
+ libraries. The second argument to com_load_typelib() may no longer be false;
+ com.autoregister_casesensitive may no longer be disabled; case-insensitive
+ markers in com.typelib_file are ignored.
-- Standard:
- . The "o" serialization format has been removed. As it is never produced by
- PHP, this may only break unserialization of manually crafted strings.
+- Date:
+ . mktime() and gmmktime() now require at least one argument. time() can be
+ used to get the current timestamp.
-========================================
-2. New Features
-========================================
+- Exif:
+ . Removed read_exif_data(). exif_read_data() should be used instead.
-- Core:
- . Added support for typed properties. For example:
+- Filter:
+ . The FILTER_FLAG_SCHEME_REQUIRED and FILTER_FLAG_HOST_REQUIRED flags for the
+ FILTER_VALIDATE_URL filter have been removed. The scheme and host are (and
+ have been) always required.
- class User {
- public int $id;
- public string $name;
- }
+- GD:
+ . The deprecated function image2wbmp() has been removed.
+ RFC: https://wiki.php.net/rfc/image2wbmp
+ . The deprecated functions png2wbmp() and jpeg2wbmp() have been removed.
+ RFC: https://wiki.php.net/rfc/deprecate-png-jpeg-2wbmp
+ . The default $mode parameter of imagecropauto() no longer accepts -1.
+ IMG_CROP_DEFAULT should be used instead.
- This will enforce that $user->id can only be assigned integer and
- $user->name can only be assigned strings. For more information see the
- RFC: https://wiki.php.net/rfc/typed_properties_v2
+- GMP:
+ . gmp_random() has been removed. One of gmp_random_range() or
+ gmp_random_bits() should be used instead.
- . Added support for coalesce assign (??=) operator. For example:
+- Intl:
+ . The deprecated constant INTL_IDNA_VARIANT_2003 has been removed.
+ RFC: https://wiki.php.net/rfc/deprecate-and-remove-intl_idna_variant_2003
+ . The deprecated Normalizer::NONE constant has been removed.
- $array['key'] ??= computeDefault();
- // is roughly equivalent to
- if (!isset($array['key'])) {
- $array['key'] = computeDefault();
- }
+- LDAP:
+ . The deprecated function ldap_sort has been removed.
- RFC: https://wiki.php.net/rfc/null_coalesce_equal_operator
+- Mbstring:
+ . The mbstring.func_overload directive has been removed. The related
+ MB_OVERLOAD_MAIL, MB_OVERLOAD_STRING, and MB_OVERLOAD_REGEX constants have
+ also been removed. Finally, the "func_overload" and "func_overload_list"
+ entries in mb_get_info() have been removed.
+ . mb_parse_str() can no longer be used without specifying a result array.
+ . A number of deprecated mbregex aliases have been removed. See the following
+ list for which functions should be used instead:
+
+ * mbregex_encoding() -> mb_regex_encoding()
+ * mbereg() -> mb_ereg()
+ * mberegi() -> mb_eregi()
+ * mbereg_replace() -> mb_ereg_replace()
+ * mberegi_replace() -> mb_eregi_replace()
+ * mbsplit() -> mb_split()
+ * mbereg_match() -> mb_ereg_match()
+ * mbereg_search() -> mb_ereg_search()
+ * mbereg_search_pos() -> mb_ereg_search_pos()
+ * mbereg_search_regs() -> mb_ereg_search_regs()
+ * mbereg_search_init() -> mb_ereg_search_init()
+ * mbereg_search_getregs() -> mb_ereg_search_getregs()
+ * mbereg_search_getpos() -> mb_ereg_search_getpos()
+ * mbereg_search_setpos() -> mb_ereg_search_setpos()
+
+ . The 'e' modifier for mb_ereg_replace() has been removed.
+ mb_ereg_replace_callback() should be used instead.
+ . A non-string pattern argument to mb_ereg_replace() will now be interpreted
+ as a string instead of an ASCII codepoint. The previous behavior may be
+ restored with an explicit call to chr().
- . Support for WeakReferences has been added.
- RFC: https://wiki.php.net/rfc/weakrefs
+- PDO:
+ . The method PDOStatement::setFetchMode() now accepts the following signature:
-- CURL:
- . CURLFile now supports stream wrappers in addition to plain file names, if
- the extension has been built against libcurl >= 7.56.0. The streams may
- need to be seekable.
+ PDOStatement::setFetchMode($mode, $classname, $params)
-- Filter:
- . The FILTER_VALIDATE_FLOAT filter now supports the min_range and max_range
- options, with the same semantics as FILTER_VALIDATE_INT.
+- PDO_ODBC:
+ . The php.ini directive pdo_odbc.db2_instance_name has been removed
-- FFI:
- . A new extension which provides a simple way to call native functions, access
- native variables and create/access data structures defined in C libraries.
- RFC: https://wiki.php.net/rfc/ffi
+- Reflection:
+ . The method signatures
-- Hash:
- . Added "crc32c" hash using Castagnoli's polynomial. This crc32 variant is
- used by storage systems, such as iSCSI, SCTP, Btrfs and ext4.
+ ReflectionClass::newInstance($args)
+ ReflectionFunction::invoke($args)
+ ReflectionMethod::invoke($object, $args)
-- Mbstring:
- . Added mb_str_split() function, which provide the same functionality as
- str_split(), but operating on code points rather than bytes.
- RFC: https://wiki.php.net/rfc/mb_str_split
+ have been changed to:
-- OPcache:
- . Support for preloading code has been added.
- RFC: https://wiki.php.net/rfc/preload
+ ReflectionClass::newInstance(...$args)
+ ReflectionFunction::invoke(...$args)
+ ReflectionMethod::invoke($object, ...$args)
-- PCRE:
- . The preg_replace_callback() and preg_replace_callback_array() functions now
- accept an additional $flags argument, with support for the
- PREG_OFFSET_CAPTURE and PREG_UNMATCHED_AS_NULL flags. This influences the
- format of the matches array passed to to the callback function.
+ Code that must be compatible with both PHP 7 and PHP 8 can use the following
+ signatures to be compatible with both versions:
-- PDO_OCI:
- . PDOStatement::getColumnMeta() is now available
+ ReflectionClass::newInstance($arg = null, ...$args)
+ ReflectionFunction::invoke($arg = null, ...$args)
+ ReflectionMethod::invoke($object, $arg = null, ...$args)
-- PDO_SQLite:
- . PDOStatement::getAttribute(PDO::SQLITE_ATTR_READONLY_STATEMENT) allows to
- check whether this statement is read-only, i.e. whether it doesn't modify
- the database.
+- SPL:
+ . SplFileObject::fgetss() has been removed.
+ . SplHeap::compare($a, $b) now specifies a method signature. Inheriting
+ classes implementing this method will now have to use a compatible
+ method signature.
- Standard:
- . strip_tags() now also accepts an array of allowed tags: Instead of
- strip_tags($str, '<a><p>') you can now write strip_tags($str, ['a', 'p']).
+ . assert() will no longer evaluate string arguments, instead they will be
+ treated like any other argument. assert($a == $b) should be used instead of
+ assert('$a == $b'). The assert.quiet_eval ini directive and
+ ASSERT_QUIET_EVAL constants have also been removed, as they would no longer
+ have any effect.
+ . parse_str() can no longer be used without specifying a result array.
+ . fgetss() has been removed.
+ . The string.strip_tags filter has been removed.
+ . The needle argument of strpos(), strrpos(), stripos(), strripos(), strstr(),
+ strchr(), strrchr(), and stristr() will now always be interpreted as a
+ string. Previously non-string needles were interpreted as an ASCII code
+ point. An explicit call to chr() can be used to restore the previous
+ behavior.
+ . The 'salt' option of password_hash() is no longer supported. If the 'salt'
+ option is used a warning is generated, the provided salt is ignored, and a
+ generated salt is used instead.
+ . The quotemeta() function will now return an empty string if an empty string
+ was passed. Previously false was returned.
+
+- XML:
+ . xml_parser_create(_ns) will now return an XmlParser object rather than a
+ resource. Return value checks using is_resource() should be replaced with
+ checks for `false`. The xml_parser_free() function no longer has an effect,
+ instead the XmlParser instance is automatically destroyed if it is no longer
+ referenced.
+
+- Zlib:
+ . gzgetss() has been removed.
- . A new mechanism for custom object serialization has been added, which
- uses two new magic methods:
-
- // Returns array containing all the necessary state of the object.
- public function __serialize(): array;
-
- // Restores the object state from the given data array.
- public function __unserialize(array $data): void;
-
- The new serialization mechanism supersedes the Serializable interface,
- which will be deprecated in the future.
-
- RFC: https://wiki.php.net/rfc/custom_object_serialization
+========================================
+2. New Features
+========================================
========================================
3. Changes in SAPI modules
@@ -196,80 +211,18 @@ PHP 7.4 UPGRADE NOTES
4. Deprecated Functionality
========================================
-- Core:
- . Unbinding $this of a non-static method through a combination of
- ReflectionMethod::getClosure() and closure rebinding is deprecated. Doing
- so is equivalent to calling a non-static method statically, which has been
- deprecated since PHP 7.0.
-
-- COM:
- . Importing type libraries with case-insensitive constant registering has been
- deprecated.
-
-- Mbstring:
- . Passing a non-string pattern to mb_ereg_replace() is deprecated. Currently
- non-string patterns are interpreted as ASCII codepoints. In PHP 8 the
- pattern will be interpreted as a string instead.
-
-- LDAP:
- . ldap_control_paged_result_response and ldap_control_paged_result are
- deprecated. Pagination controls can be sent along with ldap_search instead.
-
========================================
5. Changed Functions
========================================
-- SPL:
- . SplFileObject::fputcsv(), ::fgetcsv() and ::setCsvControl() now accept an
- empty string as $escape argument, which disables the propriertary PHP
- escaping mechanism. SplFileObject::getCsvControl() now may also return an
- empty string for the third array element, accordingly.
-
-- Standard:
- . fputcsv() and fgetcsv() now accept an empty string as $escape argument,
- which disables the propriertary PHP escaping mechanism. The behavior of
- str_getcsv() has been adjusted accordingly (formerly, an empty string was
- identical to using the default).
- . proc_open() on Windows can be passed a "create_process_group" option. It
- is required, if the child process is supposed to handle CTRL events.
-
========================================
6. New Functions
========================================
-- OpenSSL:
- . Added openssl_x509_verify(mixed cert, mixed key) function that verifies the
- signature of the certificate using a public key. A wrapper around the
- OpenSSL's X509_verify() function.
- See <https://github.com/php/php-src/pull/3624>.
-
-- Pcntl:
- . Added bool pcntl_unshare(int flags) function which allows to dissociate
- parts of the process execution context which are currently being shared with
- other processes. Explicitly, it allows you to unshare the mount, IPC, UTS,
- network, PID, user and cgroup namespaces.
-
-- SQLite3:
- . Added SQLite3Stmt::getSQL() to retrieve the SQL of the statement. If TRUE is
- passed as parameter, query parameters will be replaced in the return value
- by their currently bound value, if libsqlite ≥ 3.14 is used.
-
-- Standard
- . bool sapi_windows_set_ctrl_handler(callable handler, [, bool add = true]) -
- set or remove a handler function upon receiving a CTRL event. The handler
- function is expected have a signature "function handler(int $event)".
- . bool sapi_windows_generate_ctrl_event(int type, int pid) - send a CTRL event
- to another process.
-
========================================
7. New Classes and Interfaces
========================================
-- Reflection:
- . A new ReflectionReference class has been added, which allows detecting
- references and comparing them for identity. For more details see the RFC:
- https://wiki.php.net/rfc/reference_reflection
-
========================================
8. Removed Extensions and SAPIs
========================================
@@ -284,112 +237,10 @@ PHP 7.4 UPGRADE NOTES
9. Other Changes to Extensions
========================================
-- GD:
- . The behavior of imagecropauto() in the bundled libgd has been synced with
- that of system libgd:
- * IMG_CROP_DEFAULT is no longer falling back to IMG_CROP_SIDES
- * Threshold-cropping now uses the algorithm of system libgd
- . The default $mode parameter of imagecropauto() has been changed to
- IMG_CROP_DEFAULT; passing -1 is now deprecated.
- . imagescale() now supports aspect ratio preserving scaling to a fixed height
- by passing -1 as $new_width.
-
-- Filter:
- . The filter extension no longer exposes --with-pcre-dir for Unix builds and
- can now reliably be built as shared when using ./configure once more.
-
-- Hash:
- . The hash extension cannot be disabled anymore and is always an integral
- part of any PHP build, similar to the date extension.
-
-- Intl:
- . The Intl extension now requires at least ICU 50.1.
-
-- Libxml:
- . All libxml based extensions now require libxml 2.7.6 or newer.
-
-- Mbstring:
- . The oniguruma library is no longer bundled with PHP, instead libonig needs
- to be available on the system. Alternatively --disable-mbregex can be used
- to disable the mbregex component.
-
-- OPcache:
- . The --disable-opcache-file|--enable-opcache-file configure options have been
- removed in favor of the opcache.file_cache INI directive.
-
-- Reflection:
- . Numeric value of class, property, function and constant modifiers was
- changed. Don't filter methods and properties through
- ReflectionClass::getMethods() and ReflectionClass::getProperties(), or test
- results of Reflection...::getModifiers(), using hard-coded numeric values.
- Use corresponding constants instead (e.g. ReflectionMethod::IS_PUBLIC).
-
-- SQLite3:
- . The bundled libsqlite has been removed. To build the SQLite3 extension
- a system libsqlite3 ≥ 3.7.4 is now required. To build the PDO_SQLite
- extension a system libsqlite3 ≥ 3.5.0 is now required.
- . (Un)serialization of SQLite3, SQLite3Stmt and SQLite3Result is now explicitly
- forbidden. Formerly, serialization of instances of these classes was
- possible, but unserialization yielded unusable objects.
- . The @param notation can now also be used to denote SQL query parameters.
-
-- WDDX:
- . The WDDX extension has been deprecated and moved to PECL.
-
-- Zip:
- . The bundled libzip library has been removed. A system libzip >= 0.11 is now
- necessary to build the extension.
-
========================================
10. New Global Constants
========================================
-- Mbstring:
- . MB_ONIGURUMA_VERSION specifies the version of the oniguruma library against
- which mbregex has been built.
-
-- Socket:
- . Added FreeBSD-specific socket options:
- . SO_LABEL
- . SO_PEERLABEL
- . SO_LISTENQLIMIT
- . SO_LISTENQLEN
- . SO_USER_COOKIE
-
-- Standard:
- . PHP_WINDOWS_EVENT_CTRL_C
- . PHP_WINDOWS_EVENT_CTRL_BREAK
-
-- Tidy:
- . TIDY_TAG_ARTICLE
- . TIDY_TAG_ASIDE
- . TIDY_TAG_AUDIO
- . TIDY_TAG_BDI
- . TIDY_TAG_CANVAS
- . TIDY_TAG_COMMAND
- . TIDY_TAG_DATALIST
- . TIDY_TAG_DETAILS
- . TIDY_TAG_DIALOG
- . TIDY_TAG_FIGCAPTION
- . TIDY_TAG_FIGURE
- . TIDY_TAG_FOOTER
- . TIDY_TAG_HEADER
- . TIDY_TAG_HGROUP
- . TIDY_TAG_MAIN
- . TIDY_TAG_MARK
- . TIDY_TAG_MENUITEM
- . TIDY_TAG_METER
- . TIDY_TAG_NAV
- . TIDY_TAG_OUTPUT
- . TIDY_TAG_PROGRESS
- . TIDY_TAG_SECTION
- . TIDY_TAG_SOURCE
- . TIDY_TAG_SUMMARY
- . TIDY_TAG_TEMPLATE
- . TIDY_TAG_TIME
- . TIDY_TAG_TRACK
- . TIDY_TAG_VIDEO
-
========================================
11. Changes to INI File Handling
========================================
@@ -398,93 +249,11 @@ PHP 7.4 UPGRADE NOTES
12. Windows Support
========================================
-- stat:
- . The stat implementation has been refactored.
- - An inode number is delivered and is based on the NTFS file index.
- - The device number is now based on the volume serial number.
-
- Note, that both values derived from the system and provided as is on 64-bit
- systems. On 32-bit system, these values might overflow the 32-bit integer in
- PHP, so they're a fake.
-
-- CTRL+C and CTRL+BREAK on console can be caught by setting a handler function
- with sapi_windows_set_ctrl_handler().
-
-========================================
-13. Migration to pkg-config
-========================================
-
-A number of extensions have been migrated to exclusively use pkg-config for
-the detection of library dependencies. Generally, this means that instead of
-using --with-foo-dir=DIR or similar only --with-foo is used. Custom library
-paths can be specified either by adding additional directories to
-PKG_CONFIG_PATH or by explicitly specifying compilation options through
-FOO_CFLAGS and FOO_LIBS.
-
-The following extensions are affected:
-
-- Curl:
- . --with-curl no longer accepts a directory.
-
-- IMAP:
- . --with-kerberos no longer accepts a directory.
-
-- Intl:
- . --with-icu-dir has been removed. If --enable-intl is passed, then libicu is
- always required.
-
-- Mbstring:
- . --with-onig has been removed. Unless --disable-mbregex has been passed,
- libonig is required.
-
-- OpenSSL:
- . --with-openssl no longer accepts a directory.
- . --with-kerberos no longer accepts a directory.
-
-- PCRE:
- . --with-pcre-regex has been removed. Instead --with-external-pcre is provided
- to opt into using an external PCRE library, rather than the bundled one.
-
-- Readline:
- . --with-libedit no longer accepts a directory.
-
-- GD:
- . --with-gd becomes --enable-gd (whether to enable the extension at all) and
- --with-external-gd (to opt into using an external libgd, rather than the
- bundled one).
- . --with-png-dir has been removed. libpng is required.
- . --with-zlib-dir has been removed. zlib is required.
- . --with-freetype-dir becomes --with-freetype.
- . --with-jpeg-dir becomes --with-jpeg.
- . --with-webp-dir becomes --with-webp.
- . --with-xpm-dir becomes --with-xpm.
-
-- Libxml:
- . --with-libxml-dir has been removed.
- . --enable-libxml becomes --with-libxml.
-
-- Sodium:
- . --with-sodium no longer accepts a directory.
-
-- Zip:
- . --with-libzip has been removed.
- . --enable-zip becomes --with-zip.
-
========================================
-14. Other Changes
+13. Other Changes
========================================
========================================
-15. Performance Improvements
+14. Performance Improvements
========================================
-- Core:
- . A specialized VM opcode for the array_key_exists() function has been added,
- which improves performance of this function if it can be statically
- resolved. In namespaced code, this may require writing \array_key_exists()
- or explicitly importing the function.
-
-- PCRE:
- . When preg_match() in UTF-8 mode ("u" modifier) is repeatedly called on the
- same string (but possibly different offsets), it will only be checked for
- UTF-8 validity once.