Skip to content

Upgrade Emscripten version #2116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: trunk
Choose a base branch
from
Draft
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
36 changes: 36 additions & 0 deletions package-lock.json

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

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -171,6 +171,7 @@
"eslint-plugin-playground-dev": "file:packages/meta/src/eslint-plugin-playground-dev",
"eslint-plugin-react": "7.32.2",
"eslint-plugin-react-hooks": "4.6.0",
"estree-toolkit": "1.7.8",
"gh-pages": "5.0.0",
"glob": "^9.3.0",
"husky": "8.0.3",
@@ -180,6 +181,7 @@
"jsdom": "22.1.0",
"jsonc-eslint-parser": "^2.1.0",
"lerna": "6.6.2",
"meriyah": "6.0.3",
"nx": "16.9.0",
"ora": "6.3.0",
"prettier": "^2.6.2",
9 changes: 4 additions & 5 deletions packages/php-wasm/compile/base-image/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Originally forked from https://github.com/seanmorris/php-wasm
# ubuntu:lunar supports amd64 and arm64 (Apple Silicon) while
# emscripten/emsdk:3.1.24 supports amd64 only.
FROM ubuntu:lunar as emscripten
# ubuntu:noble supports amd64 and arm64 (Apple Silicon)
FROM ubuntu:noble as emscripten

SHELL ["/bin/bash", "-c"]

@@ -50,8 +49,8 @@ RUN set -euxo pipefail;\
# https://github.com/WordPress/wordpress-playground/tree/67d916b5eccfe78e26e9c953598cc1a81f316931/packages/php-wasm/compile
RUN ln -s /usr/bin/python3 /usr/bin/python
RUN git clone https://github.com/emscripten-core/emsdk.git && \
./emsdk/emsdk install 3.1.61 && \
/root/emsdk/emsdk activate 3.1.61
./emsdk/emsdk install 3.1.74 && \
/root/emsdk/emsdk activate 3.1.74

RUN mkdir -p /root/lib/lib /root/lib/include /root/lib/share /root/lib/bin

7 changes: 6 additions & 1 deletion packages/php-wasm/compile/php/Dockerfile
Original file line number Diff line number Diff line change
@@ -1021,6 +1021,9 @@ RUN set -euxo pipefail; \
# Postprocess the build php.js module:
COPY ./php/esm-prefix.js /root/esm-prefix.js
COPY ./php/esm-suffix.js /root/esm-suffix.js
COPY ./php/esm-php-exit-status.js /root/esm-php-exit-status.js
RUN apt-get install -y nodejs npm
COPY ./php/override-php-exit-status.js /root/override-php-exit-status.js
RUN set -euxo pipefail; \
cp -rfv /build/output/* /root/output/; \
# Figure out the target file names and URLs
@@ -1048,7 +1051,7 @@ RUN set -euxo pipefail; \
# This assumes the traffic is always forwarded to the same target.
# However, we want to support arbitrary targets, so we need to
# replace the hardcoded websocket target URL with a dynamic callback.
/root/replace.sh $'s/if\s*\(\s*["\']string["\']\s*===\s*typeof Module\[["\']websocket["\']\]\[["\']url["\']\]\s*\)/if("function"===typeof Module["websocket"]["url"]) {\nurl = Module["websocket"]["url"](...arguments);\n}else if ("string" === typeof Module["websocket"]["url"])/g' \
/root/replace.sh $'s/if\s*\(\s*SOCKFS\.websocketArgs\["url"\]\s*\)/if("function"===typeof SOCKFS.websocketArgs["url"]) {\nurl = SOCKFS.websocketArgs["url"](...arguments);\n}else if ("string" === typeof SOCKFS.websocketArgs["url"])/g' \
/root/output/php.js; \
# Enable custom WebSocket constructors to support socket options.
/root/replace.sh "s/ws\s*=\s*new WebSocketConstructor/if (Module['websocket']['decorator']) {WebSocketConstructor = Module['websocket']['decorator'](WebSocketConstructor);}ws = new WebSocketConstructor/g" /root/output/php.js && \
@@ -1099,6 +1102,8 @@ RUN set -euxo pipefail; \
cat /root/esm-prefix.js >> /root/output/php-module.js && \
cat /root/output/php.js >> /root/output/php-module.js && \
cat /root/esm-suffix.js >> /root/output/php-module.js && \
npm install estree-toolkit meriyah && \
node /root/override-php-exit-status.js /root/output/php-module.js && \
\
# Remove the old php.js file
rm /root/output/php.js && \
34 changes: 34 additions & 0 deletions packages/php-wasm/compile/php/esm-php-exit-status.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Overrides Emscripten's default ExitStatus object which gets
* thrown on failure. Unfortunately, the default object is not
* a subclass of Error and does not provide any stack trace.
*
* This is a deliberate behavior on Emscripten's end to prevent
* memory leaks after the program exits. See:
*
* https://github.com/emscripten-core/emscripten/pull/9108
*
* In case of WordPress Playground, the worker in which the PHP
* runs will typically exit after the PHP program finishes, so
* we don't have to worry about memory leaks.
*
* As for assigning to a previously undeclared ExitStatus variable here,
* the Emscripten module declares `ExitStatus` as `function ExitStatus`
* which means it gets hoisted to the top of the scope and can be
* reassigned here – before the actual declaration is reached.
*
* If that sounds weird, try this example:
*
* ExitStatus = () => { console.log("reassigned"); }
* function ExitStatus() {}
* ExitStatus();
* // logs "reassigned"
*/
ExitStatus = class PHPExitStatus extends Error {
constructor(status) {
super(status);
this.name = "ExitStatus";
this.message = "Program terminated with exit(" + status + ")";
this.status = status;
}
}
35 changes: 0 additions & 35 deletions packages/php-wasm/compile/php/esm-prefix.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,2 @@
export function init(RuntimeName, PHPLoader) {
/**
* Overrides Emscripten's default ExitStatus object which gets
* thrown on failure. Unfortunately, the default object is not
* a subclass of Error and does not provide any stack trace.
*
* This is a deliberate behavior on Emscripten's end to prevent
* memory leaks after the program exits. See:
*
* https://github.com/emscripten-core/emscripten/pull/9108
*
* In case of WordPress Playground, the worker in which the PHP
* runs will typically exit after the PHP program finishes, so
* we don't have to worry about memory leaks.
*
* As for assigning to a previously undeclared ExitStatus variable here,
* the Emscripten module declares `ExitStatus` as `function ExitStatus`
* which means it gets hoisted to the top of the scope and can be
* reassigned here – before the actual declaration is reached.
*
* If that sounds weird, try this example:
*
* ExitStatus = () => { console.log("reassigned"); }
* function ExitStatus() {}
* ExitStatus();
* // logs "reassigned"
*/
ExitStatus = class PHPExitStatus extends Error {
constructor(status) {
super(status);
this.name = "ExitStatus";
this.message = "Program terminated with exit(" + status + ")";
this.status = status;
}
}

// The rest of the code comes from the built php.js file and esm-suffix.js
36 changes: 36 additions & 0 deletions packages/php-wasm/compile/php/override-php-exit-status.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as path from 'path';
import * as fs from 'fs';
import { traverse } from 'estree-toolkit';
import { parseModule } from 'meriyah';

const thisScriptDir = path.dirname(process.argv[1]);

const phpJsPath = process.argv[2];
const phpJs = fs.readFileSync(phpJsPath, 'utf8');
const enhancedExitStatusJsPath = path.resolve(
thisScriptDir,
'esm-php-exit-status.js'
);
const enhancedExitStatusJs = fs.readFileSync(enhancedExitStatusJsPath, 'utf8');

const phpJsAst = parseModule(phpJs, { ranges: true });
console.log(phpJsAst);

traverse(phpJsAst, {
ClassDeclaration(path) {
console.log(path.node);
if (path.node?.id?.name === 'ExitStatus') {
const endOfClassDeclaration = path.node.range[1];
const head = phpJs.substring(0, endOfClassDeclaration);
const tail = phpJs.substring(endOfClassDeclaration);

const output = `${head}\n${enhancedExitStatusJs}\n${tail}`;
console.log(output);
fs.writeFileSync(phpJsPath, output);
process.exit(0);
}
}
});

console.error('Did not find ExitStatus declaration to override.');
process.exit(-1);

Unchanged files with check annotations Beta

// @ts-ignore
import url from './sqlite-database-integration.zip?url';
/**

Check warning on line 5 in packages/playground/wordpress-builds/src/sqlite-database-integration/get-sqlite-database-plugin-details.ts

GitHub Actions / Lint and typecheck

Comments may not exceed 100 characters
* This file was auto generated by packages/playground/wordpress-builds/build/refresh-sqlite-integration-plugin.js
* DO NOT CHANGE MANUALLY!
* This file must statically exists in the project because of the way