Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,22 @@ PHP_FUNCTION(post_message_to_js)
char *data;
int data_len;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &data, &data_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len) == FAILURE) {
return;
}

char *response;
size_t response_len = js_module_onMessage(data, &response);
if (response_len != -1) {
if (response_len != (size_t)-1) {
#if PHP_MAJOR_VERSION >= 7
zend_string *return_string = zend_string_init(response, response_len, 0);
free(response);
RETURN_NEW_STR(return_string);
#else
RETVAL_STRINGL(response, response_len, 1);
free(response);
return;
#endif
} else {
RETURN_NULL();
}
Expand Down
33 changes: 27 additions & 6 deletions packages/php-wasm/compile/php-wasm-dns-polyfill/dns_polyfill.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,27 @@ PHP_FUNCTION(dns_check_record)
HEADER *hp;
querybuf answer = {0};
char *hostname;
#if PHP_MAJOR_VERSION >= 7
size_t hostname_len;
size_t rectype_len = 0;
zend_string *rectype = NULL;
#else
int hostname_len;
int rectype_len = 0;
char *rectype = NULL;
#endif
int type = DNS_T_MX, i;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &hostname, &hostname_len, &rectype, &rectype_len) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &hostname, &hostname_len, &rectype, &rectype_len) == FAILURE) {
return;
}

if (hostname_len == 0) {
php_error_docref(NULL, E_WARNING, "Host cannot be empty");
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Host cannot be empty");
RETURN_FALSE;
}

php_error_docref(NULL, E_WARNING, "dns_check_record() always returns false in PHP.wasm.");
php_error_docref(NULL TSRMLS_CC, E_WARNING, "dns_check_record() always returns false in PHP.wasm.");

RETURN_FALSE;
}
Expand All @@ -143,8 +149,13 @@ PHP_FUNCTION(dns_check_record)
PHP_FUNCTION(dns_get_record)
{
char *hostname;
#if PHP_MAJOR_VERSION >= 7
size_t hostname_len;
zend_long type_param = PHP_DNS_ANY;
#else
int hostname_len;
long type_param = PHP_DNS_ANY;
#endif
zval *authns = NULL, *addtl = NULL;
int type_to_fetch;
int dns_errno;
Expand All @@ -155,7 +166,7 @@ PHP_FUNCTION(dns_get_record)
int type, first_query = 1, store_results = 1;
zend_bool raw = 0;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lz!z!b",
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz!z!b",
&hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) {
return;
}
Expand All @@ -173,7 +184,7 @@ PHP_FUNCTION(dns_get_record)
}
}

php_error_docref(NULL, E_WARNING, "dns_get_record() always returns an empty array in PHP.wasm.");
php_error_docref(NULL TSRMLS_CC, E_WARNING, "dns_get_record() always returns an empty array in PHP.wasm.");

/* Initialize the return array */
array_init(return_value);
Expand All @@ -186,7 +197,11 @@ PHP_FUNCTION(dns_get_record)
PHP_FUNCTION(dns_get_mx)
{
char *hostname;
#if PHP_MAJOR_VERSION >= 7
size_t hostname_len;
#else
int hostname_len;
#endif
zval *mx_list, *weight_list = NULL;
int count, qdc;
u_short type, weight;
Expand All @@ -196,12 +211,18 @@ PHP_FUNCTION(dns_get_mx)
uint8_t *cp, *end;
int i;

#if PHP_MAJOR_VERSION >= 7
ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_STRING(hostname, hostname_len)
Z_PARAM_ZVAL(mx_list)
Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(weight_list)
ZEND_PARSE_PARAMETERS_END();
#else
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) {
return;
}
#endif

array_init(mx_list);
if (!mx_list) {
Expand All @@ -215,7 +236,7 @@ PHP_FUNCTION(dns_get_mx)
}
}

php_error_docref(NULL, E_WARNING, "dns_get_mx() always returns an empty array in PHP.wasm.");
php_error_docref(NULL TSRMLS_CC, E_WARNING, "dns_get_mx() always returns an empty array in PHP.wasm.");

RETURN_FALSE;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "Zend/zend_alloc.h"
#include "php_wasm_memory_storage.h"

#if PHP_MAJOR_VERSION >= 7

/**
* Allocate a chunk of memory.
*
Expand Down Expand Up @@ -112,6 +114,22 @@ PHP_MSHUTDOWN_FUNCTION(wasm_memory_storage)
return SUCCESS;
}

#else /* PHP < 7 */

/* Custom memory storage is not available in PHP 5.x.
* Provide no-op MINIT/MSHUTDOWN. */
PHP_MINIT_FUNCTION(wasm_memory_storage)
{
return SUCCESS;
}

PHP_MSHUTDOWN_FUNCTION(wasm_memory_storage)
{
return SUCCESS;
}

#endif /* PHP_MAJOR_VERSION >= 7 */

/* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(wasm_memory_storage)
{
Expand Down
65 changes: 40 additions & 25 deletions packages/php-wasm/compile/php/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -289,14 +289,16 @@ RUN cd /root && \
git apply --no-index /root/php${PHP_VERSION:0:3}*.patch -v && \
chmod +x /root/apply-mysqlnd-patch.sh && \
/root/apply-mysqlnd-patch.sh && \
if [[ "${PHP_VERSION:0:3}" < '8.3' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-up-to-8.2.patch -v; \
elif [[ "${PHP_VERSION:0:3}" == '8.3' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-8.3.patch -v; \
elif [[ "${PHP_VERSION:0:3}" == '8.4' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-8.4.patch -v; \
elif [[ "${PHP_VERSION:0:3}" == '8.5' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-8.5.patch -v; \
if [[ "${PHP_VERSION:0:1}" -ge "7" ]]; then \
if [[ "${PHP_VERSION:0:3}" < '8.3' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-up-to-8.2.patch -v; \
elif [[ "${PHP_VERSION:0:3}" == '8.3' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-8.3.patch -v; \
elif [[ "${PHP_VERSION:0:3}" == '8.4' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-8.4.patch -v; \
elif [[ "${PHP_VERSION:0:3}" == '8.5' ]]; then \
git apply --no-index /root/php-chunk-alloc-zend-assert-8.5.patch -v; \
fi; \
fi && \
touch php-src/patched

Expand All @@ -308,7 +310,9 @@ RUN if [ "$WITH_MYSQL" = "yes" ]; then \

# Download and prepare imagick extension if needed (PHP 7.4+)
# Use version 3.7.0 for PHP 7.x, master for PHP 8.x
RUN if [ "${PHP_VERSION:0:1}" -eq "7" ]; then \
# Skip entirely for PHP 5.x (imagick 3.7+ requires PHP 7+)
RUN if [ "${PHP_VERSION:0:1}" -ge "7" ]; then \
if [ "${PHP_VERSION:0:1}" -eq "7" ]; then \
IMAGICK_BRANCH="3.7.0"; \
else \
IMAGICK_BRANCH="master"; \
Expand All @@ -330,13 +334,22 @@ RUN if [ "${PHP_VERSION:0:1}" -eq "7" ]; then \
./buildconf --force; \
fi && \
echo -n ' --with-imagick=/root/lib --with-imagick-config=/root/lib/bin/wasm32-unknown-emscripten-MagickWand-config ' >> /root/.php-configure-flags && \
echo -n ' /root/lib/lib/libMagickWand-7.Q16HDRI.a /root/lib/lib/libMagickCore-7.Q16HDRI.a ' >> /root/.emcc-php-wasm-sources
echo -n ' /root/lib/lib/libMagickWand-7.Q16HDRI.a /root/lib/lib/libMagickCore-7.Q16HDRI.a ' >> /root/.emcc-php-wasm-sources; \
fi

# Disable phar.php generation for all builds (WASM binaries can't execute during build)
# This must run after buildconf but before configure
RUN /root/replace.sh 's/pharcmd=pharcmd/pharcmd=/g' /root/php-src/configure && \
/root/replace.sh 's/pharcmd_install=install-pharcmd/pharcmd_install=/g' /root/php-src/configure

# Fibers are a PHP 8.1+ feature. They are compiled as a custom assembly
# implementation by default. However, that implementation does not work with
# emscripten. The line below disables it for PHP 8.1+.
# See https://github.com/WordPress/wordpress-playground/issues/92
RUN if [[ "${PHP_VERSION:0:1}" -gt "8" || ( "${PHP_VERSION:0:1}" -eq "8" && "${PHP_VERSION:2:1}" -ge "1" ) ]]; then \
echo -n ' --disable-fiber-asm ' >> /root/.php-configure-flags; \
fi

# Build the patched PHP
WORKDIR /root/php-src
RUN source /root/emsdk/emsdk_env.sh && \
Expand All @@ -356,16 +369,8 @@ RUN source /root/emsdk/emsdk_env.sh && \
PKG_CONFIG_PATH="/root/lib/lib/pkgconfig:${PKG_CONFIG_PATH}" \
emconfigure ./configure \
PKG_CONFIG_PATH=$PKG_CONFIG_PATH \
# Fibers are a PHP 8.1+ feature. They are compiled as
# a custom assembly implementation by default. However,
# that implementation does not work with emscripten.
# --disable-fiber-asm is added via .php-configure-flags for PHP 8.1+ only
#
# The line below disables it, forcing PHP to use the
# C implementation instead.
#
# See https://github.com/WordPress/wordpress-playground/issues/92
# for more context.
--disable-fiber-asm \
--enable-phar \
# --enable-json for PHP < 8.0:
--enable-json \
Expand Down Expand Up @@ -431,10 +436,17 @@ fi;
RUN echo '#undef HAVE_ASM_GOTO' >> /root/php-src/main/php_config.h;
RUN echo '#define HAVE_ASM_GOTO 0' >> /root/php-src/main/php_config.h;
# Disable asm arithmetic.
RUN /root/replace.sh 's/ZEND_USE_ASM_ARITHMETIC 1/ZEND_USE_ASM_ARITHMETIC 0/g' /root/php-src/Zend/zend_operators.h;
RUN /root/replace.sh 's/defined\(__GNUC__\)/0/g' /root/php-src/Zend/zend_multiply.h
RUN /root/replace.sh 's/defined\(__GNUC__\)/0/g' /root/php-src/Zend/zend_cpuinfo.c
RUN /root/replace.sh 's/defined\(__clang__\)/0/g' /root/php-src/Zend/zend_cpuinfo.c
# ZEND_USE_ASM_ARITHMETIC was introduced in PHP 7.x, zend_cpuinfo.c in PHP 7.1
RUN if [ -f /root/php-src/Zend/zend_operators.h ] && grep -q 'ZEND_USE_ASM_ARITHMETIC' /root/php-src/Zend/zend_operators.h; then \
/root/replace.sh 's/ZEND_USE_ASM_ARITHMETIC 1/ZEND_USE_ASM_ARITHMETIC 0/g' /root/php-src/Zend/zend_operators.h; \
fi
RUN if [ -f /root/php-src/Zend/zend_multiply.h ]; then \
/root/replace.sh 's/defined\(__GNUC__\)/0/g' /root/php-src/Zend/zend_multiply.h; \
fi
RUN if [ -f /root/php-src/Zend/zend_cpuinfo.c ]; then \
/root/replace.sh 's/defined\(__GNUC__\)/0/g' /root/php-src/Zend/zend_cpuinfo.c; \
/root/replace.sh 's/defined\(__clang__\)/0/g' /root/php-src/Zend/zend_cpuinfo.c; \
fi
# }}}

# With HAVE_UNISTD_H=1 PHP complains about the missing getdtablesize() function
Expand All @@ -461,8 +473,11 @@ RUN /root/replace.sh 's/#define VCWD_POPEN.+/#define VCWD_POPEN(command, type) w
RUN echo 'extern FILE *wasm_popen(const char *cmd, const char *mode);' >> /root/php-src/Zend/zend_virtual_cwd.h

# Provide a custom implementation of the shutdown() function.
RUN perl -pi.bak -e $'s/(\s+)shutdown\(/$1 wasm_shutdown(/g' /root/php-src/sapi/cli/php_cli_server.c
RUN perl -pi.bak -e $'s/(\s+)closesocket\(/$1 wasm_close(/g' /root/php-src/sapi/cli/php_cli_server.c
# php_cli_server.c exists in PHP 5.4+ (built-in server added in 5.4)
RUN if [ -f /root/php-src/sapi/cli/php_cli_server.c ]; then \
perl -pi.bak -e $'s/(\\s+)shutdown\\(/$1 wasm_shutdown(/g' /root/php-src/sapi/cli/php_cli_server.c; \
perl -pi.bak -e $'s/(\\s+)closesocket\\(/$1 wasm_close(/g' /root/php-src/sapi/cli/php_cli_server.c; \
fi

# Provide custom implementation fo the shutdown() function.
# This is used by intl ( which links C++ code ) and need C linkage.
Expand Down
9 changes: 5 additions & 4 deletions packages/php-wasm/compile/php/apply-mysqlnd-patch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
TARGET_FILE="php-src/ext/mysqlnd/mysqlnd_connection.c"

if [ ! -f "$TARGET_FILE" ]; then
echo "Error: $TARGET_FILE not found"
exit 1
echo "Skipping mysqlnd patch: $TARGET_FILE not found (may not exist in this PHP version)"
exit 0
fi

if grep -q "effective_host" "$TARGET_FILE"; then
Expand All @@ -31,6 +31,7 @@ else
if [ -f "$TARGET_FILE.bak" ]; then
mv "$TARGET_FILE.bak" "$TARGET_FILE"
fi
echo "Failed to apply mysqlnd patch to $TARGET_FILE"
exit 1
echo "Warning: Could not apply mysqlnd patch to $TARGET_FILE (pattern not found, may be a different PHP version)"
# Don't fail - older PHP versions have different mysqlnd code
exit 0
fi
24 changes: 24 additions & 0 deletions packages/php-wasm/compile/php/php5.6.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
diff --git a/php-src/ext/standard/file.c b/php-src/ext/standard/file.c
--- a/php-src/ext/standard/file.c
+++ b/php-src/ext/standard/file.c
@@ -1627,6 +1627,19 @@
goto safe_to_copy;
break;
case 0:
+ // Fix for https://github.com/WordPress/wordpress-playground/issues/54:
+ // Problem: Calling copy() on an empty source file crashes the JavaScript
+ // runtime.
+ // Solution: Avoid copying empty files. Just create an empty
+ // destination file and return.
+ if (src_s.sb.st_size == 0) {
+ char *opened_path = NULL;
+ php_stream *stream = php_stream_open_wrapper(dest, "w", REPORT_ERRORS, &opened_path);
+ if (stream) {
+ php_stream_close(stream);
+ return SUCCESS;
+ }
+ return FAILURE;
+ }
break;
default: /* failed to stat file, does not exist? */
return ret;
Loading