Skip to content

Commit

Permalink
Play with async fs functions
Browse files Browse the repository at this point in the history
  • Loading branch information
adamziel committed Oct 9, 2024
1 parent e9c514b commit 180ff11
Show file tree
Hide file tree
Showing 7 changed files with 4,305 additions and 171 deletions.
1 change: 0 additions & 1 deletion packages/php-wasm/compile/php/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,6 @@ RUN set -euxo pipefail; \
"_wasm_set_phpini_path", \n\
"_wasm_add_SERVER_entry", \n\
"_wasm_add_ENV_entry", \n\
"_wasm_read", \n\
"_wasm_free", \n\
"_wasm_sapi_handle_request", \n\
"_wasm_sapi_request_shutdown", \n\
Expand Down
59 changes: 11 additions & 48 deletions packages/php-wasm/compile/php/php_wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,29 +443,6 @@ static size_t handle_line(int type, zval *array, char *buf, size_t bufl)
return bufl;
}

/**
* Shims read(2) functionallity.
* Enables reading from blocking pipes. By default, Emscripten
* will throw an EWOULDBLOCK error when trying to read from a
* blocking pipe. This function overrides that behavior and
* instead waits for the pipe to become readable.
*
* @see https://github.com/WordPress/wordpress-playground/issues/951
* @see https://github.com/emscripten-core/emscripten/issues/13214
*/
EMSCRIPTEN_KEEPALIVE ssize_t wasm_read(int fd, void *buf, size_t count)
{
struct __wasi_iovec_t iov = {
.buf = buf,
.buf_len = count};
size_t num;
if (__wasi_syscall_ret(js_fd_read(fd, &iov, 1, &num)))
{
return -1;
}
return num;
}

/*
* If type==0, only last line of output is returned (exec)
* If type==1, all lines will be printed and last lined returned (system)
Expand Down Expand Up @@ -588,31 +565,6 @@ EMSCRIPTEN_KEEPALIVE int wasm_php_exec(int type, const char *cmd, zval *array, z

int wasm_socket_has_data(php_socket_t fd);

/* hybrid select(2)/poll(2) for a single descriptor.
* timeouttv follows same rules as select(2), but is reduced to millisecond accuracy.
* Returns 0 on timeout, -1 on error, or the event mask (ala poll(2)).
*/
EMSCRIPTEN_KEEPALIVE inline int php_pollfd_for(php_socket_t fd, int events, struct timeval *timeouttv)
{
php_pollfd p;
int n;

p.fd = fd;
p.events = events;
p.revents = 0;

// must yield back to JS event loop to get the network response:
wasm_poll_socket(fd, events, php_tvtoto(timeouttv));

n = php_poll2(&p, 1, php_tvtoto(timeouttv));

if (n > 0)
{
return p.revents;
}

return n;
}

ZEND_BEGIN_ARG_INFO_EX(arginfo_post_message_to_js, 0, 1, 1)
ZEND_ARG_INFO(0, data)
Expand Down Expand Up @@ -1737,6 +1689,17 @@ int php_wasm_init()
backend_t opfs = wasmfs_create_opfs_backend();
err = wasmfs_create_directory("/internal", 0777, opfs);

backend_t opfs2 = wasmfs_create_opfs_backend();
err = wasmfs_create_directory("/internal2", 0777, opfs2);

FILE *file = fopen("/internal2/hi.txt", "w");
if (file != NULL) {
fprintf(file, "Hello World");
fclose(file);
} else {
fprintf(stderr, "Error creating file in /internal2/hi.txt\n");
}

wasm_server_context = malloc(sizeof(wasm_server_context_t));
wasm_init_server_context();

Expand Down
25 changes: 14 additions & 11 deletions packages/php-wasm/universal/src/lib/fs-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export class FSHelpers {
path: string,
data: string | Uint8Array
) {
FS.writeFile(path, data);
return FS.writeFile(path, data);
}

/**
Expand Down Expand Up @@ -159,12 +159,12 @@ export class FSHelpers {
* @returns The list of files and directories in the given directory.
*/
@rethrowFileSystemError('Could not list files in "{path}"')
static listFiles(
static async listFiles(
FS: Emscripten.RootFS,
path: string,
options: ListFilesOptions = { prependPath: false }
): string[] {
if (!FSHelpers.fileExists(FS, path)) {
): Promise<string[]> {
if (!(await FSHelpers.fileExists(FS, path))) {
return [];
}
try {
Expand All @@ -190,8 +190,8 @@ export class FSHelpers {
* @returns True if the path is a directory, false otherwise.
*/
@rethrowFileSystemError('Could not stat "{path}"')
static isDir(FS: Emscripten.RootFS, path: string): boolean {
if (!FSHelpers.fileExists(FS, path)) {
static async isDir(FS: Emscripten.RootFS, path: string): boolean {

Check failure on line 193 in packages/php-wasm/universal/src/lib/fs-helpers.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<boolean>'?
if (!(await FSHelpers.fileExists(FS, path))) {
return false;
}
return FS.isDir(FS.lookupPath(path, { follow: true }).node.mode);
Expand All @@ -205,8 +205,8 @@ export class FSHelpers {
* @returns True if the path is a file, false otherwise.
*/
@rethrowFileSystemError('Could not stat "{path}"')
static isFile(FS: Emscripten.RootFS, path: string): boolean {
if (!FSHelpers.fileExists(FS, path)) {
static async isFile(FS: Emscripten.RootFS, path: string): Promise<boolean> {
if (!(await FSHelpers.fileExists(FS, path))) {
return false;
}
return FS.isFile(FS.lookupPath(path, { follow: true }).node.mode);
Expand Down Expand Up @@ -269,9 +269,12 @@ export class FSHelpers {
* @returns True if the file exists, false otherwise.
*/
@rethrowFileSystemError('Could not stat "{path}"')
static fileExists(FS: Emscripten.RootFS, path: string): boolean {
static async fileExists(
FS: Emscripten.RootFS,
path: string
): Promise<boolean> {
try {
FS.lookupPath(path);
await FS.lookupPath(path);
return true;
} catch (e) {
return false;
Expand All @@ -288,7 +291,7 @@ export class FSHelpers {
*/
@rethrowFileSystemError('Could not create directory "{path}"')
static mkdir(FS: Emscripten.RootFS, path: string) {
FS.mkdirTree(path);
return FS.mkdirTree(path);
}

@rethrowFileSystemError('Could not copy files from "{path}"')
Expand Down
18 changes: 5 additions & 13 deletions packages/php-wasm/universal/src/lib/php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,11 +406,11 @@ export class PHP implements Disposable {
if (!this.#webSapiInitialized) {
await this.#initWebRuntime();
this.#webSapiInitialized = true;
this.mkdir('/internal');
this.mkdir('/internal/shared');
this.mkdir('/internal/shared/preload');
await this.mkdir('/internal');
await this.mkdir('/internal/shared');
await this.mkdir('/internal/shared/preload');
}
console.log(this.listFiles('/'));
console.log(await this.listFiles('/internal'));

Check warning on line 413 in packages/php-wasm/universal/src/lib/php.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

Unexpected console statement
if (request.scriptPath && !this.fileExists(request.scriptPath)) {
throw new Error(
`The script path "${request.scriptPath}" does not exist.`
Expand All @@ -432,7 +432,7 @@ export class PHP implements Disposable {
heapBodyPointer = this.#setRequestBody(request.body);
}
if (typeof request.code === 'string') {
this.writeFile('/internal/eval.php', request.code);
await this.writeFile('/internal/eval.php', request.code);
this.#setScriptPath('/internal/eval.php');
} else if (typeof request.scriptPath === 'string') {
this.#setScriptPath(request.scriptPath || '');
Expand Down Expand Up @@ -535,14 +535,6 @@ export class PHP implements Disposable {
httpStatusCode: number;
} {
const headersFilePath = '/internal/headers.json';
setTimeout(() => {
console.log('Waa');
console.log(this.listFiles('/'));
console.log(this.listFiles('/internal'));
console.log(this.listFiles('/wordpress'));
console.log(this.listFiles('/opfs'));
}, 1000);
console.log('Woo');
if (!this.fileExists(headersFilePath)) {
return { headers: {}, httpStatusCode: 200 };
throw new Error(
Expand Down
Binary file modified packages/php-wasm/web/public/php/jspi/8_0_30/php_8_0.wasm
Binary file not shown.
4,355 changes: 4,260 additions & 95 deletions packages/php-wasm/web/public/php/jspi/php_8_0.js

Large diffs are not rendered by default.

18 changes: 15 additions & 3 deletions packages/playground/wordpress/src/boot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,21 @@ export async function bootWordPress(options: BootOptions) {

const php = await requestHandler.getPrimaryPhp();
console.log(await php.mkdir('/wordpress'));

Check warning on line 185 in packages/playground/wordpress/src/boot.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

Unexpected console statement
console.log(await php.listFiles('/'));
console.log((await php.run({ code: '<?php echo "Hello, World!";' })).bytes);
throw new Error('Waa');
// console.log(await php.listFiles('/'));
console.log(

Check warning on line 187 in packages/playground/wordpress/src/boot.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

Unexpected console statement
(await php.run({ code: '<?php print_r(glob("/internal/shared/*"));' }))
.text
);

console.log((await php.run({ code: '<?php echo "Hello, World!";' })).text);

Check warning on line 192 in packages/playground/wordpress/src/boot.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

Unexpected console statement
// console.log((await php.run({ code: '<?php print_r(glob("/wordpress/*"));' })).text);
console.log(

Check warning on line 194 in packages/playground/wordpress/src/boot.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

Unexpected console statement
(await php.run({ code: '<?php print_r(glob("/internal/*"));' })).text
);
console.log(

Check warning on line 197 in packages/playground/wordpress/src/boot.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

Unexpected console statement
(await php.run({ code: '<?php print_r(glob("/internal/*"));' })).text
);
console.log((await php.run({ code: '<?php echo "Hello, World!";' })).text);

Check warning on line 200 in packages/playground/wordpress/src/boot.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

Unexpected console statement

if (options.hooks?.beforeWordPressFiles) {
await options.hooks.beforeWordPressFiles(php);
Expand Down

0 comments on commit 180ff11

Please sign in to comment.