Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
23ad778
Add PHP 5.6 type system and version support
JanJakes Apr 6, 2026
7239b50
Compile PHP 5.6 to WebAssembly
JanJakes Apr 6, 2026
1ffb9bd
Add PHP 5.6 compatibility transpiler
JanJakes Apr 6, 2026
bb05178
Add pre-patched SQLite v2.2.22 for PHP 5.6
JanJakes Apr 6, 2026
88094dc
Add legacy WordPress boot support
JanJakes Apr 7, 2026
5faf2dc
Integrate legacy PHP/WP support in web worker and CLI
JanJakes Apr 7, 2026
fe74004
Add CI job for legacy WordPress boot testing
JanJakes Apr 7, 2026
57ca3a8
Resolve bare WP version strings to wordpress.org downloads
JanJakes Apr 7, 2026
142d2a4
Fix wp-admin loading on legacy WordPress versions
JanJakes Apr 7, 2026
ae6a2d4
Disable 1Password on legacy wp-login.php forms
JanJakes Apr 9, 2026
ac35495
Serialize concurrent requests in SinglePHPInstanceManager
JanJakes Apr 10, 2026
60a57ee
Skip PROXYFS mmap for legacy PHP to fix multi-instance parsing
JanJakes Apr 10, 2026
4453873
Fix WP 2.0 admin permission errors by resetting cached current_user
JanJakes Apr 10, 2026
97f4326
Fix relative include() paths in wp-admin for legacy WordPress
JanJakes Apr 10, 2026
ece83ec
Avoid polluting global $content in SQLite preload guard
JanJakes Apr 10, 2026
f0d3abe
Fix WP 1.0 siteurl by reading correct requestHandler property
JanJakes Apr 10, 2026
7cbde0c
Register query filter in placeholder_escape polyfill to fix mangled p…
JanJakes Apr 10, 2026
dd63a6b
Fix double-quoted include/require paths in wp-admin patching
JanJakes Apr 10, 2026
51af4d2
Fix auto-login on WordPress 1.0-2.5
JanJakes Apr 10, 2026
f172807
Fix nonce verification failures on legacy WordPress 3.5–4.5
JanJakes Apr 10, 2026
514bb17
Flush rewrite rules after setting permalink structure
JanJakes Apr 10, 2026
b8c1880
Suppress "Creating default object from empty value" warnings
JanJakes Apr 10, 2026
e51e7a1
Patch admin-ajax.php auth for WP 2.5-2.7 in Playground
JanJakes Apr 10, 2026
8b3c1d3
Flush rewrite rules on first request via mu-plugin
JanJakes Apr 10, 2026
b07fe3e
Set permalink_structure via PDO for legacy WordPress
JanJakes Apr 10, 2026
263dc16
Fix post querying by ID and pretty permalink on WP 2.5–3.5
JanJakes Apr 10, 2026
a54e76d
Extend legacy WP test script with post, plugin, and nonce tests
JanJakes Apr 10, 2026
9fbbf53
Replace closures in add_action/add_filter with named functions
JanJakes Apr 10, 2026
738d0ec
Fix post view test on WP 4.7-4.9 and newPost detection on WP 3.3
JanJakes Apr 10, 2026
57d2491
Fix auto-login on front page for WP < 2.8
JanJakes Apr 10, 2026
67bc800
Fix auto-login and front page regressions on WP 2.1-2.7
JanJakes Apr 10, 2026
ed716da
Add option_siteurl/option_home filters for legacy WP < 2.2
JanJakes Apr 10, 2026
4a46abd
Adapt playground_add_filter to WP 1.0 and WP 1.2 hook formats
JanJakes Apr 10, 2026
121ad3b
Fix WP 1.5-2.4 admin: empty dashboard and referrer errors
JanJakes Apr 10, 2026
29d6f98
Update test script comment about version coverage
JanJakes Apr 10, 2026
7ad70bf
Fix check_admin_referer patch to handle WP 1.2's nested braces
JanJakes Apr 10, 2026
4b4f0eb
Test new post and plugin activation on all WP versions
JanJakes Apr 11, 2026
8ab9b77
Pass required second argument to do_action in WP 1.2 referer patch
JanJakes Apr 11, 2026
5a35967
Define missing global error() stub for WP 1.5 RSS functions
JanJakes Apr 11, 2026
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
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,34 @@ jobs:
node-version: 20
- run: packages/php-wasm/cli/tests/smoke-test.sh

# Legacy WordPress boot test - verifies that WordPress versions
# 1.2 through 4.9 boot on PHP 5.6 with SQLite and show "Hello world!"
test-legacy-wp-version-boot:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
submodules: true
- uses: ./.github/actions/prepare-playground
- name: Install Playwright Browser
run: npx playwright install chromium --with-deps
- name: Start dev server
run: |
npm run dev > /tmp/playground-dev.log 2>&1 &
timeout=120; elapsed=0
until curl -s -o /dev/null http://127.0.0.1:5400/website-server/ 2>/dev/null; do
sleep 3
elapsed=$((elapsed + 3))
if [ $elapsed -ge $timeout ]; then
echo "Dev server failed to start within ${timeout}s"
cat /tmp/playground-dev.log | tail -50
exit 1
fi
done
- name: Test legacy WordPress version boot
run: node packages/playground/wordpress/tests/test-legacy-wp-version-boot.mjs

# Redis extension tests - verifies the php-redis extension loads
# and provides the expected API, and can connect to a real Redis server.
# Redis requires JSPI because asyncify cannot properly handle exceptions
Expand Down
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
Loading
Loading