Skip to content

Commit e0b8815

Browse files
authored
Add OPCache support (#2400)
This PR is created from #2290 The Github UI is stuck using that PR, so a new PR has been created. https://a8c.slack.com/archives/C04BURZDHFH/p1753189537944499 ## Motivation for the change, related issues Related to #2251 With this PR, we are adding support for OPCache by introducing a new `WITH_OPCACHE` argument, `true` by default. ## Implementation details The OPCache library is always compiled as a [dynamic library](https://github.com/php/php-src/blob/master/ext/opcache/config.m4#L29-L30). Once #2248 is merged, we can proceed to use the dynamic library generated instead of forcing a static compilation by patching `ext/opcache/config.m4`. ### Caching mechanism The OPCache [.m4 file](https://github.com/php/php-src/blob/master/ext/opcache/config.m4) performs a series of tests. | Feature checks | 7.0 | 7.1 | 7.2 | 7.3 | 7.4 | 8.0 | 8.1 | 8.2 | 8.3 | 8.4 | | -------------------- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | `OPCACHE_FILE_CACHE` | ✅ | ✅ | ✅ | ✅ | | | | | | | | `HUGE_CODE_PAGES` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | `JIT` | | | | | | ✅ | ✅ | ✅ | ✅ | ✅ | | `MPROTECT` | ✅ | ✅ | ✅ | ✅ | | | | | | | | `SHM_IPC` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | `SHM_MMAP_ANON` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | `SHM_MMAP_ZERO` | ✅ | ✅ | ✅ | ✅ | | | | | | | | `SHM_MMAP_POSIX` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | `SHM_MMAP_FILE` | ✅ | ✅ | ✅ | ✅ | | | | | | | In this PR, we force the Autoconf to recognize the `mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);` emulated shared (anonymous) memory by renaming `have_shm_mmap_anon` (renamed to `php_cv_shm_mmap_anon` in PHP 8.4). ### Additional Starting with Python 3.12, distutils was removed from the standard library after being [deprecated](https://peps.python.org/pep-0632/) in Python 3.10. Here, we force the last version to ensure that `node-gyp/gyp/gyp_main.py` does not crash during compilation because it does not find the module. ## Testing Instructions (or ideally a Blueprint) ## First test Open `phpinfo.php` and search for \"Zend OPCache\". It should be \"Up and Running\" and \"OK\" on startup ### Second test Try [this blueprint](http://127.0.0.1:5400/website-server/#eyJsYW5kaW5nUGFnZSI6Ii9vcGNhY2hlLnBocCIsInByZWZlcnJlZFZlcnNpb25zIjp7InBocCI6IjguNCIsIndwIjoiNi44LjEifSwic3RlcHMiOlt7InN0ZXAiOiJ3cml0ZUZpbGUiLCJwYXRoIjoiL3dvcmRwcmVzcy9vcGNhY2hlLnBocCIsImRhdGEiOiI8P3BocFxucmVxdWlyZV9vbmNlICd3cC1sb2FkLnBocCc7XG4kc3RhdHVzID0gb3BjYWNoZV9nZXRfc3RhdHVzKCk7XG5cbmlmKGlzX2FycmF5KCRzdGF0dXMpKSB7XG4gICAgLy91bnNldCggJHN0YXR1c1snc2NyaXB0cyddICk7XG59XG5cbiRodHRwX3Jlc3BvbnNlcyA9IFtdO1xuJHRvdGFsX3Jlc3BvbnNlID0gMDtcbiRwYWdlcyA9IFtcbiAgICAnLycsXG4gICAgJy8yMDI1LzA0LzMwL2hlbGxvLXdvcmxkLycsXG4gICAgJy9zYW1wbGUtcGFnZS8nLFxuICAgICcvd3AtYWRtaW4vJyxcbiAgICAnL3dwLWFkbWluL2VkaXQucGhwJyxcbiAgICAnL2ZlZWQvJyxcbiAgICAnL2NvbW1lbnRzL2ZlZWQvJyxcbiAgICAnL3dwLWpzb24vd3AvdjIvcG9zdHMnLFxuXTtcblxuZm9yZWFjaCAoJHBhZ2VzIGFzICRwYWdlKSB7XG4gICAgZm9yICgkaSA9IDA7ICRpIDwgMzsgKyskaSkge1xuICAgICAgICAkc3RhcnRfdGltZSA9IG1pY3JvdGltZSggdHJ1ZSApO1xuICAgICAgICAkaHR0cF9yZXNwb25zZSA9IHdwX3JlbW90ZV9nZXQoIGhvbWVfdXJsKCAkcGFnZSApICk7XG4gICAgICAgICRlbmRfdGltZSA9IG1pY3JvdGltZSggdHJ1ZSApO1xuICAgICAgICAkZGVsdGEgPSByb3VuZCgoICRlbmRfdGltZSAtICRzdGFydF90aW1lICkgKiAxMDAwKTtcbiAgICAgICAgJHJlc3BvbnNlID0gW1xuICAgICAgICAgICAgJ3BhZ2UnID0+ICRwYWdlLFxuICAgICAgICAgICAgJ3RpbWUnID0+ICRkZWx0YSxcbiAgICAgICAgICAgICdzdGF0dXMnID0+ICcnLFxuICAgICAgICBdO1xuXG4gICAgICAgICR0b3RhbF9yZXNwb25zZSArPSAkZGVsdGE7XG5cbiAgICAgICAgaWYgKCBpc193cF9lcnJvciggJGh0dHBfcmVzcG9uc2UgKSApIHtcbiAgICAgICAgICAgICRyZXNwb25zZVsnc3RhdHVzJ10gPSAnZXJyb3InO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAkcmVzcG9uc2VbJ3N0YXR1cyddID0gd3BfcmVtb3RlX3JldHJpZXZlX3Jlc3BvbnNlX2NvZGUoICRodHRwX3Jlc3BvbnNlICk7XG5cbiAgICAgICAgJGh0dHBfcmVzcG9uc2VzW10gPSAkcmVzcG9uc2U7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjKCRzaXplKSB7XG4gICAgJHVuaXQgPSBbJ0InLCAnS0InLCAnTUInLCAnR0InLCAnVEInLCAnUEInXTtcblxuICAgIHJldHVybiBAcm91bmQoJHNpemUgLyBwb3coMTAyNCwgKCRpID0gZmxvb3IobG9nKCRzaXplLCAxMDI0KSkpKSwgMikgLiAnICcgLiAkdW5pdFskaV07XG59XG5cbiRjb25maWd1cmF0aW9uID0gb3BjYWNoZV9nZXRfY29uZmlndXJhdGlvbigpO1xuLy8gdW5zZXQoICRzdGF0dXNbJ3NjcmlwdHMnXSApO1xuXG4kcmVzID0gW1xuICAgICdjYWNoZWQnID0+IGlzX2FycmF5KCRzdGF0dXMpLFxuICAgICd2ZXJzaW9uJyA9PiAkY29uZmlndXJhdGlvblsndmVyc2lvbiddWyd2ZXJzaW9uJ10sXG4gICAgJ3RvdGFsX3Jlc3BvbnNlJyA9PiAkdG90YWxfcmVzcG9uc2UsXG4gICAgJ3Jlc3BvbnNlcycgPT4gJGh0dHBfcmVzcG9uc2VzLFxuICAgICdtZW1vcnknID0+IFtcbiAgICAgICAgJ21lbScgPT4gYyhtZW1vcnlfZ2V0X3VzYWdlKCkpLFxuICAgICAgICAncmVhbCcgPT4gYyhtZW1vcnlfZ2V0X3VzYWdlKHRydWUpKSxcbiAgICAgICAgJ3BlYWsnID0+IGMobWVtb3J5X2dldF9wZWFrX3VzYWdlKCkpLFxuICAgICAgICAncmVhbF9wZWFrJyA9PiBjKG1lbW9yeV9nZXRfcGVha191c2FnZSh0cnVlKSlcbiAgICBdLFxuICAgIC8vICdmaWxlcycgPT4gcygnL2ludGVybmFsL3NoYXJlZC9vcGNhY2hlJyksXG4gICAgJ2NvbmZpZ3VyYXRpb24nID0+ICRjb25maWd1cmF0aW9uWydkaXJlY3RpdmVzJ10sXG4gICAgJ3N0YXR1cycgPT4gJHN0YXR1c1xuXTtcblxuZWNobyAnPGJ1dHRvbiBvbmNsaWNrPVwiZG93bmxvYWRKc29uKClcIj5Eb3dubG9hZCBKU09OPC9idXR0b24+JztcbmVjaG8gJzxzY3JpcHQ+XG5mdW5jdGlvbiBkb3dubG9hZEpzb24oKSB7XG4gICAgLy8gQ3JlYXRlIEpTT04gZGF0YVxuICAgIGNvbnN0IGRhdGEgPSAnIC4ganNvbl9lbmNvZGUoJHJlcykgLiAnO1xuXG4gICAgLy8gQ3JlYXRlIGJsb2IgYW5kIGRvd25sb2FkIGxpbmtcbiAgICBjb25zdCBibG9iID0gbmV3IEJsb2IoW0pTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsIDIpXSwge3R5cGU6IFwiYXBwbGljYXRpb24vanNvblwifSk7XG4gICAgY29uc3QgdXJsID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYik7XG4gICAgY29uc3QgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xuICAgIGEuaHJlZiA9IHVybDtcbiAgICBhLmRvd25sb2FkID0gXCJvcGNhY2hlLXN0YXRzLmpzb25cIjtcblxuICAgIC8vIFRyaWdnZXIgZG93bmxvYWRcbiAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpO1xuICAgIGEuY2xpY2soKTtcblxuICAgIC8vIENsZWFudXBcbiAgICB3aW5kb3cuVVJMLnJldm9rZU9iamVjdFVSTCh1cmwpO1xuICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG59XG48L3NjcmlwdD4nO1xuXG5lY2hvICc8YSBocmVmPVwiL3dwLWFkbWluXCI+d3AtYWRtaW48L2E+PGJyPjxwcmU+JywganNvbl9lbmNvZGUoJHJlcywgSlNPTl9QUkVUVFlfUFJJTlQpLCAnPC9wcmU+JzsifV19) (https://gist.github.com/zaerl/3e60bff32e1e915d5acc509bd50e9762). It will load WordPress +20 times so it will not open immediately. \"Cached\" should be `true`, all the GET responses 200 OK. The `opcache_enabled` field will be `false`. It is a well-known PHP ~~feature~~ [bug](https://bugs.php.net/bug.php?id=75070). Now open `packages/php-wasm/universal/src/lib/php.ts` and comment out these two lines: ```php // 'opcache.file_cache_only = 1', // 'opcache.file_cache_consistency_checks = 1', ``` The same page will show more details and an hit rate ~75%. Now visit `wp-admin`, open some page. Go back to `opcache.php`, it should show ~90% or better.
1 parent 0f789d0 commit e0b8815

File tree

92 files changed

+2990
-4464
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+2990
-4464
lines changed

.gitattributes

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ packages/docs/site/static/diagrams.excalidraw linguist-documentation=true
44
packages/php-wasm/compile/*/dist linguist-vendored
55
packages/php-wasm/compile/libz/zlib-src linguist-vendored
66
packages/php-wasm/node/public/ linguist-generated=true
7+
packages/php-wasm/node/asyncify/** linguist-generated=true -diff
8+
packages/php-wasm/node/jspi/** linguist-generated=true -diff
79
packages/php-wasm/node/src/test/test-data/ linguist-generated=true
8-
packages/php-wasm/web/public/php/ linguist-generated=true -diff
10+
packages/php-wasm/web/public/php/** linguist-generated=true -diff
911
packages/playground/sync/src/test/wp-* linguist-generated=true
1012
packages/playground/remote/public/wp-* linguist-generated=true -diff
1113
packages/playground/remote/src/wordpress linguist-generated=true -diff

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,10 @@ php.js.bak
6565
# Since it is dynamically generated from the Node.js TLS module,
6666
# we do not want to commit it to the repository.
6767
packages/php-wasm/cli/src/ca-bundle.crt
68+
69+
# PHPUnit
70+
.phpunit.result.cache
71+
72+
# Debug artifacts generated by the build with --WITH_DEBUG, --WITH_SOURCEMAPS.
73+
packages/php-wasm/**/php-src/*
74+
packages/php-wasm/**/php.wasm.map

packages/php-wasm/compile/build.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ const argParser = yargs(process.argv.slice(2))
162162
description: 'OpenSSL version to use',
163163
default: '1.1.0h',
164164
},
165+
WITH_OPCACHE: {
166+
type: 'string',
167+
description: 'Build with OPCache support',
168+
},
169+
STACK_SIZE: {
170+
type: 'string',
171+
description: 'The emscripten stack size to use for the build',
172+
default: '1MB',
173+
},
165174
});
166175

167176
const args = argParser.argv;
@@ -183,6 +192,8 @@ const platformDefaults = {
183192
WITH_INTL: 'yes',
184193
WITH_OPENSSL: 'yes',
185194
WITH_WS_NETWORKING_PROXY: 'yes',
195+
WITH_OPCACHE: 'yes',
196+
STACK_SIZE: '1MB',
186197
},
187198
web: {},
188199
node: {
@@ -286,6 +297,10 @@ await asyncSpawn(
286297
`EMSCRIPTEN_ENVIRONMENT=${platform === 'node' ? 'node' : 'web'}`,
287298
'--build-arg',
288299
getArg('WITH_JSPI'),
300+
'--build-arg',
301+
getArg('WITH_OPCACHE'),
302+
'--build-arg',
303+
getArg('STACK_SIZE'),
289304
],
290305
{ cwd: sourceDir, stdio: 'inherit' }
291306
);
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* This file is a dummy file for the opcache extension. It is used to build the
3+
* opcache extension as a static extension.
4+
*/
5+
6+
#include "php.h"
7+
#include "php_opcache.h"
8+
#include "Zend/zend_extensions.h"
9+
10+
/* Dummy module functions */
11+
PHP_MINIT_FUNCTION(opcache)
12+
{
13+
/**
14+
* Register the Zend extension
15+
*
16+
* NOTE: The name `zend_extension_entry` sounds generic but actually
17+
* references the opcache-specific variable declared here:
18+
* https://github.com/php/php-src/blob/0f731b455c3759cd15698d8aeb98535feb86f8f1/ext/opcache/ZendAccelerator.c#L5022
19+
*/
20+
extern zend_extension zend_extension_entry;
21+
zend_register_extension(&zend_extension_entry, NULL);
22+
return SUCCESS;
23+
}
24+
25+
/* Dummy module shutdown function */
26+
PHP_MSHUTDOWN_FUNCTION(opcache)
27+
{
28+
/* The actual shutdown is handled by the Zend extension */
29+
return SUCCESS;
30+
}
31+
32+
/* Dummy PHP module entry for static builds */
33+
zend_module_entry opcache_module_entry = {
34+
STANDARD_MODULE_HEADER,
35+
"opcache",
36+
NULL, /* functions */
37+
PHP_MINIT(opcache),
38+
PHP_MSHUTDOWN(opcache),
39+
NULL, /* RINIT */
40+
NULL, /* RSHUTDOWN */
41+
NULL, /* MINFO */
42+
PHP_VERSION,
43+
STANDARD_MODULE_PROPERTIES
44+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* This file is a dummy file for the opcache extension. It is used to build the
3+
* opcache extension as a static extension.
4+
*/
5+
6+
#ifndef PHP_OPCACHE_H
7+
#define PHP_OPCACHE_H
8+
9+
extern zend_module_entry opcache_module_entry;
10+
#define phpext_opcache_ptr &opcache_module_entry
11+
12+
#endif /* PHP_OPCACHE_H */

packages/php-wasm/compile/php-wasm-memory-storage/wasm_memory_storage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
/**
2626
* Allocate a chunk of memory.
2727
*
28-
* This function implements the PHP Zend custom memory storage operation "chunk_free()".
28+
* This function implements the PHP Zend custom memory storage operation "chunk_alloc()".
2929
*
3030
* Here is an example offered in the PHP source code:
3131
* https://github.com/php/php-src/blob/dbaeb62ab1e34067057170ab50cf39d1bde584d8/Zend/zend_alloc.h#L325

packages/php-wasm/compile/php/Dockerfile

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ ARG WITH_JSPI="no"
1010
# but just "7" is invalid because there's no branch PHP-7.
1111
ARG PHP_VERSION
1212

13+
# Whether to build the opcache extension. The .m4 file is patched before the main
14+
# ./buildconf script is generated.
15+
ARG WITH_OPCACHE
16+
1317
# Clone PHP
1418
RUN git clone https://github.com/php/php-src.git php-src \
1519
--branch PHP-$PHP_VERSION \
@@ -25,6 +29,9 @@ COPY ./php-wasm-dns-polyfill/ /root/php-src/ext/dns_polyfill
2529
# Polyfill for post_message_to_js functions
2630
COPY ./php-post-message-to-js/ /root/php-src/ext/post_message_to_js
2731

32+
# Copy the dummy opcache_module.c and php_opcache.h files.
33+
COPY ./opcache/ /root/php-src/ext/opcache
34+
2835
# Bring in the libraries
2936
RUN mkdir -p /root/lib/include /root/lib/lib /libs
3037
COPY ./bison2.7/dist/ /libs/bison2.7
@@ -81,6 +88,31 @@ RUN if [[ "${PHP_VERSION:0:1}" -eq "7" && "${PHP_VERSION:2:1}" -le "3" ]]; then
8188
cp /root/builds/libsqlite3/\<7\.4/sqlite_config0.m4 /root/php-src/ext/sqlite3/config0.m4; \
8289
fi;
8390

91+
# Patch OPcache config.m4 file if needed
92+
RUN if [ "$WITH_OPCACHE" = "yes" ]; \
93+
then \
94+
# Ensure mmap() shared memory is recognized, even if not true.
95+
# This will #declare HAVE_SHM_MMAP_ANON 1 in php_config.h
96+
if [[ "${PHP_VERSION:0:1}" -eq "8" && "${PHP_VERSION:2:1}" -eq "4" ]]; then \
97+
# Name changed in 8.4. See https://github.com/php/php-src/commit/ca55603d8a27b4e1f9c12cf72acd0fd39a6ac059
98+
/root/replace.sh 's/php_cv_shm_mmap_anon=no/php_cv_shm_mmap_anon=yes/g' /root/php-src/ext/opcache/config.m4; \
99+
else \
100+
/root/replace.sh 's/have_shm_mmap_anon=no/have_shm_mmap_anon=yes/g' /root/php-src/ext/opcache/config.m4; \
101+
# PHP bug: PHP_NEW_EXTENSION do not read $ext_shared from the config.m4 file.
102+
# https://github.com/php/php-src/blob/f35a22adba8a7ddf709c6cc98ecb57ba4dd8fe8c/ext/opcache/config.m4#L313
103+
/root/replace.sh 's/shared,,/no,,/g' /root/php-src/ext/opcache/config.m4; \
104+
fi; \
105+
# Force OPcache to be built as a static extension. OPcache is always built as a shared extension.
106+
/root/replace.sh 's/ext_shared=yes/ext_shared=no/g' /root/php-src/ext/opcache/config.m4; \
107+
# Add the dummy opcache_module.c to the list of files to build.
108+
/root/replace.sh 's/shared_alloc_mmap.c/shared_alloc_mmap.c opcache_module.c/g' /root/php-src/ext/opcache/config.m4; \
109+
# Enable OPcache.
110+
echo -n ' --enable-opcache --disable-opcache-jit --disable-huge-code-pages ' >> /root/.php-configure-flags; \
111+
else \
112+
# Be sure to disable OPcache if not needed.
113+
echo -n ' --disable-opcache ' >> /root/.php-configure-flags; \
114+
fi
115+
84116
RUN cd php-src && ./buildconf --force
85117

86118
# Build PHP
@@ -2063,6 +2095,7 @@ COPY ./php/phpwasm-emscripten-library-file-locking-for-node.js /root/phpwasm-ems
20632095
COPY ./php/phpwasm-emscripten-library-known-undefined-functions.js /root/phpwasm-emscripten-library-known-undefined-functions.js
20642096
ARG WITH_SOURCEMAPS
20652097
ARG WITH_DEBUG
2098+
ARG STACK_SIZE
20662099
RUN set -euxo pipefail; \
20672100
mkdir -p /build/output; \
20682101
source /root/emsdk/emsdk_env.sh; \
@@ -2134,6 +2167,7 @@ RUN set -euxo pipefail; \
21342167
-s MIN_NODE_VERSION=200900 \
21352168
-s INITIAL_MEMORY=1024MB \
21362169
-s ALLOW_MEMORY_GROWTH=1 \
2170+
-s STACK_SIZE="$STACK_SIZE" \
21372171
-s ASSERTIONS=0 \
21382172
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \
21392173
-s NODEJS_CATCH_EXIT=0 \
@@ -2191,7 +2225,7 @@ RUN set -euxo pipefail; \
21912225
/root/replace.sh "s/if\s*\(stream\.stream_ops\.poll\)/if (stream.stream_ops?.poll)/g" /root/output/php.js; \
21922226
# Emscripten allows only directories to be mounted, but in Playground we support mounting files, directories, and symlinks.
21932227
# For file mounting to work, we need to remove the directory check.
2194-
/root/replace-across-lines.sh 's/(\s+)if\s*\(\s*!FS\.isDir\(node\.mode\)\s*\)\s*\{\s+throw\s+new\s+FS\.ErrnoError\(54\)\s*;\s+\}(\s+)/$1$2/s' /root/output/php.js; \
2228+
/root/replace-across-lines.sh 's/(\s*)if\s*\(\s*!FS\.isDir\(node\.mode\)\s*\)\s*\{\s*throw\s*new\s*FS\.ErrnoError\(54\)\s*;?\s*\}(\s*)/$1$2/s' /root/output/php.js; \
21952229
# Make Emscripten websockets configurable
21962230
# Emscripten makes the Websocket proxy connect to a fixed URL.
21972231
# This assumes the traffic is always forwarded to the same target.
@@ -2273,6 +2307,7 @@ RUN set -euxo pipefail; \
22732307
fi; \
22742308
echo "export { dependencyFilename }; " >> /root/output/php-module.js && \
22752309
echo "export const dependenciesTotalSize = $FILE_SIZE; " >> /root/output/php-module.js && \
2310+
echo "const phpVersionString = '$PHP_VERSION';" >> /root/output/php-module.js && \
22762311
cat /root/esm-prefix.js >> /root/output/php-module.js && \
22772312
cat /root/output/php.js >> /root/output/php-module.js && \
22782313
cat /root/esm-suffix.js >> /root/output/php-module.js && \

packages/php-wasm/compile/php/esm-suffix.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,15 @@ if (typeof NODEFS === 'object') {
8282
};
8383
}
8484

85+
/**
86+
* Expose the PHP version so the PHP class can make version-specific
87+
* adjustments to `php.ini`.
88+
*/
89+
PHPLoader['phpVersion'] = (() => {
90+
const [ major, minor, patch ] = phpVersionString.split('.').map(Number);
91+
return { major, minor, patch };
92+
})();
93+
8594
return PHPLoader;
8695

8796
// Close the opening bracket from esm-prefix.js:
Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
1+
diff --git a/php-src/ext/opcache/zend_accelerator_debug.c b/php-src/ext/opcache/zend_accelerator_debug.c
2+
index 4932999b624..c3f034855b5 100644
3+
--- a/php-src/ext/opcache/zend_accelerator_debug.c
4+
+++ b/php-src/ext/opcache/zend_accelerator_debug.c
5+
@@ -25,6 +25,9 @@
6+
#include <time.h>
7+
#ifdef ZEND_WIN32
8+
# include <process.h>
9+
+#else
10+
+/* Error: call to undeclared function 'getpid' */
11+
+# include <unistd.h>
12+
#endif
13+
#include "ZendAccelerator.h"
14+
115
diff --git a/php-src/ext/pdo_sqlite/sqlite_statement.c b/php-src/ext/pdo_sqlite/sqlite_statement.c
16+
index 817e6294db1..2a30874f1c5 100644
217
--- a/php-src/ext/pdo_sqlite/sqlite_statement.c
318
+++ b/php-src/ext/pdo_sqlite/sqlite_statement.c
4-
@@ -299,7 +299,7 @@ static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
19+
@@ -261,7 +261,7 @@ static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
520
return 1;
621
}
7-
22+
823
-static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees)
924
+static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees)
1025
{
1126
pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
1227
if (!S->stmt) {
13-
14-
1528
diff --git a/php-src/ext/standard/file.c b/php-src/ext/standard/file.c
29+
index 0bb81cae8ba..f5ffbe48b65 100644
1630
--- a/php-src/ext/standard/file.c
1731
+++ b/php-src/ext/standard/file.c
18-
@@ -1691,18 +1691,32 @@ PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_flg, php
19-
php_stream *srcstream = NULL, *deststream = NULL;
20-
int ret = FAILURE;
21-
php_stream_statbuf src_s, dest_s;
22-
23-
switch (php_stream_stat_path_ex(src, 0, &src_s, ctx)) {
24-
case -1:
25-
/* non-statable stream */
32+
@@ -1666,6 +1666,20 @@ PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_flg, php
2633
goto safe_to_copy;
2734
break;
2835
case 0:
@@ -43,24 +50,20 @@ diff --git a/php-src/ext/standard/file.c b/php-src/ext/standard/file.c
4350
break;
4451
default: /* failed to stat file, does not exist? */
4552
return ret;
46-
}
47-
if (S_ISDIR(src_s.sb.st_mode)) {
48-
php_error_docref(NULL, E_WARNING, "The first argument to copy() function cannot be a directory");
49-
return FAILURE;
50-
}
5153
diff --git a/php-src/main/streams/cast.c b/php-src/main/streams/cast.c
54+
index fe56c9b0b5d..ea3fd445911 100644
5255
--- a/php-src/main/streams/cast.c
5356
+++ b/php-src/main/streams/cast.c
54-
@@ -113,10 +113,10 @@ static int stream_cookie_seeker(void *cookie, __off64_t *position, int whence)
57+
@@ -115,10 +115,10 @@ static int stream_cookie_seeker(void *cookie, __off64_t *position, int whence)
5558
return 0;
5659
}
5760
# else
5861
-static int stream_cookie_seeker(void *cookie, zend_off_t position, int whence)
5962
+static int stream_cookie_seeker(void *cookie, long long *position, int whence)
6063
{
61-
64+
6265
- return php_stream_seek((php_stream *)cookie, position, whence);
6366
+ return php_stream_seek((php_stream *)cookie, *position, whence);
6467
}
6568
# endif
66-
69+
Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
1+
diff --git a/php-src/ext/opcache/zend_accelerator_debug.c b/php-src/ext/opcache/zend_accelerator_debug.c
2+
index bd3e55d6948..f0bc4cba61e 100644
3+
--- a/php-src/ext/opcache/zend_accelerator_debug.c
4+
+++ b/php-src/ext/opcache/zend_accelerator_debug.c
5+
@@ -25,6 +25,9 @@
6+
#include <time.h>
7+
#ifdef ZEND_WIN32
8+
# include <process.h>
9+
+#else
10+
+/* Error: call to undeclared function 'getpid' */
11+
+# include <unistd.h>
12+
#endif
13+
#include "ZendAccelerator.h"
14+
115
diff --git a/php-src/ext/pdo_sqlite/sqlite_statement.c b/php-src/ext/pdo_sqlite/sqlite_statement.c
16+
index 4437bbbde03..66d2a581a02 100644
217
--- a/php-src/ext/pdo_sqlite/sqlite_statement.c
318
+++ b/php-src/ext/pdo_sqlite/sqlite_statement.c
4-
@@ -299,7 +299,7 @@ static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
19+
@@ -261,7 +261,7 @@ static int pdo_sqlite_stmt_describe(pdo_stmt_t *stmt, int colno)
520
return 1;
621
}
7-
22+
823
-static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong *len, int *caller_frees)
924
+static int pdo_sqlite_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, size_t *len, int *caller_frees)
1025
{
1126
pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
1227
if (!S->stmt) {
13-
14-
1528
diff --git a/php-src/ext/standard/file.c b/php-src/ext/standard/file.c
29+
index 99abee6676a..2c175428fac 100644
1630
--- a/php-src/ext/standard/file.c
1731
+++ b/php-src/ext/standard/file.c
18-
@@ -1691,18 +1691,32 @@ PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_flg, php
19-
php_stream *srcstream = NULL, *deststream = NULL;
20-
int ret = FAILURE;
21-
php_stream_statbuf src_s, dest_s;
22-
23-
switch (php_stream_stat_path_ex(src, 0, &src_s, ctx)) {
24-
case -1:
25-
/* non-statable stream */
32+
@@ -1666,6 +1666,20 @@ PHPAPI int php_copy_file_ctx(const char *src, const char *dest, int src_flg, php
2633
goto safe_to_copy;
2734
break;
2835
case 0:
@@ -43,24 +50,20 @@ diff --git a/php-src/ext/standard/file.c b/php-src/ext/standard/file.c
4350
break;
4451
default: /* failed to stat file, does not exist? */
4552
return ret;
46-
}
47-
if (S_ISDIR(src_s.sb.st_mode)) {
48-
php_error_docref(NULL, E_WARNING, "The first argument to copy() function cannot be a directory");
49-
return FAILURE;
50-
}
5153
diff --git a/php-src/main/streams/cast.c b/php-src/main/streams/cast.c
54+
index 9ef542086cc..26c90594d86 100644
5255
--- a/php-src/main/streams/cast.c
5356
+++ b/php-src/main/streams/cast.c
54-
@@ -113,10 +113,10 @@ static int stream_cookie_seeker(void *cookie, __off64_t *position, int whence)
57+
@@ -115,10 +115,10 @@ static int stream_cookie_seeker(void *cookie, __off64_t *position, int whence)
5558
return 0;
5659
}
5760
# else
5861
-static int stream_cookie_seeker(void *cookie, zend_off_t position, int whence)
5962
+static int stream_cookie_seeker(void *cookie, long long *position, int whence)
6063
{
61-
64+
6265
- return php_stream_seek((php_stream *)cookie, position, whence);
6366
+ return php_stream_seek((php_stream *)cookie, *position, whence);
6467
}
6568
# endif
66-
69+

0 commit comments

Comments
 (0)