Skip to content

Commit d6691fe

Browse files
committed
Some cleanup. More needed.
1 parent 4ca23c4 commit d6691fe

File tree

9 files changed

+146
-158
lines changed

9 files changed

+146
-158
lines changed

packages/php-wasm/cli/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ ${process.argv[0]} ${process.execArgv.join(' ')} ${process.argv[1]}
8989
const sysTempDir = mkdtempSync(path.join(os.tmpdir(), 'php-wasm-sys-tmp'));
9090
const php = new PHP(
9191
await loadNodeRuntime(phpVersion, {
92+
fileLockManager: new FileLockManagerForNode(),
9293
emscriptenOptions: {
93-
fileLockManager: new FileLockManagerForNode(),
9494
processId: 1,
9595
ENV: {
9696
...envVariables,

packages/php-wasm/compile/php/phpwasm-emscripten-library-file-locking-for-node.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ const LibraryForFileLocking = {
5252
#if ASYNCIFY == 2
5353
return Asyncify.handleAsync(async () => {
5454
#endif
55-
return userSpace.fcntl64(fd, cmd, varargs);
55+
if (!PHPLoader.fileLockManager) {
56+
return _builtin_fcntl64(fd, cmd, varargs);
57+
}
58+
return Module['userSpace'].fcntl64(fd, cmd, varargs);
5659
#if ASYNCIFY == 2
5760
});
5861
#endif
@@ -69,7 +72,7 @@ const LibraryForFileLocking = {
6972
#if ASYNCIFY == 2
7073
return Asyncify.handleAsync(async () => {
7174
#endif
72-
return userSpace.flock(fd, op);
75+
return Module['userSpace'].flock(fd, op);
7376
#if ASYNCIFY == 2
7477
});
7578
#endif
@@ -88,7 +91,7 @@ const LibraryForFileLocking = {
8891
#if ASYNCIFY == 2
8992
return Asyncify.handleAsync(async () => {
9093
#endif
91-
return userSpace.fd_close(fd);
94+
return Module['userSpace'].fd_close(fd);
9295
#if ASYNCIFY == 2
9396
});
9497
#endif
@@ -104,7 +107,7 @@ const LibraryForFileLocking = {
104107
#if ASYNCIFY == 2
105108
return Asyncify.handleAsync(async () => {
106109
#endif
107-
return userSpace.js_release_file_locks();
110+
return Module['userSpace'].js_release_file_locks();
108111
#if ASYNCIFY == 2
109112
});
110113
#endif

packages/php-wasm/compile/php/phpwasm-emscripten-library.js

Lines changed: 75 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
const LibraryExample = {
1111
// Emscripten dependencies:
1212
$PHPWASM__deps: ['$allocateUTF8OnStack'],
13-
$PHPWASM__postset: 'PHPWASM.init(PHPLoader?.phpWasmInitOptions);',
13+
$PHPWASM__postset: 'PHPWASM.init();',
1414

1515
// Functions not exposed to C but available in the generated
1616
// JavaScript library under the PHPWASM object:
@@ -28,71 +28,78 @@ const LibraryExample = {
2828
// emscripten_O_NDELAY |
2929
// emscripten_O_DIRECT |
3030
// emscripten_O_NOATIME
31-
init: function (phpWasmInitOptions) {
32-
// TODO: Consider limiting this to Node.js builds.
33-
if (phpWasmInitOptions.bindUserSpace) {
34-
phpWasmInitOptions.bindUserSpace({
35-
// TODO: Require PID instead of defaulting to 42.
36-
pid: PHPLoader.processId ?? 42,
37-
// TODO: When receiving this context, validate that all these fields exist.
38-
constants: {
39-
F_GETFL: Number('{{{cDefs.F_GETFL}}}'),
40-
O_ACCMODE: Number('{{{cDefs.O_ACCMODE}}}'),
41-
O_RDONLY: Number('{{{cDefs.O_RDONLY}}}'),
42-
O_WRONLY: Number('{{{cDefs.O_WRONLY}}}'),
43-
O_APPEND: Number('{{{cDefs.O_APPEND}}}'),
44-
O_NONBLOCK: Number('{{{cDefs.O_NONBLOCK}}}'),
45-
F_SETFL: Number('{{{cDefs.F_SETFL}}}'),
46-
F_GETLK: Number('{{{cDefs.F_GETLK}}}'),
47-
F_SETLK: Number('{{{cDefs.F_SETLK}}}'),
48-
F_SETLKW: Number('{{{cDefs.F_SETLKW}}}'),
49-
SEEK_SET: Number('{{{cDefs.SEEK_SET}}}'),
50-
SEEK_CUR: Number('{{{cDefs.SEEK_CUR}}}'),
51-
SEEK_END: Number('{{{cDefs.SEEK_END}}}'),
52-
F_GETFL: Number('{{{cDefs.F_GETFL}}}'),
53-
O_ACCMODE: Number('{{{cDefs.O_ACCMODE}}}'),
54-
O_RDONLY: Number('{{{cDefs.O_RDONLY}}}'),
55-
O_WRONLY: Number('{{{cDefs.O_WRONLY}}}'),
56-
O_APPEND: Number('{{{cDefs.O_APPEND}}}'),
57-
O_NONBLOCK: Number('{{{cDefs.O_NONBLOCK}}}'),
58-
F_SETFL: Number('{{{cDefs.F_SETFL}}}'),
59-
F_GETLK: Number('{{{cDefs.F_GETLK}}}'),
60-
F_SETLK: Number('{{{cDefs.F_SETLK}}}'),
61-
F_SETLKW: Number('{{{cDefs.F_SETLKW}}}'),
62-
SEEK_SET: Number('{{{cDefs.SEEK_SET}}}'),
63-
SEEK_CUR: Number('{{{cDefs.SEEK_CUR}}}'),
64-
SEEK_END: Number('{{{cDefs.SEEK_END}}}'),
65-
// From:
66-
// https://github.com/emscripten-core/emscripten/blob/66d2137b0381ac35f7e2346b2d6a90abd0f1211a/system/lib/libc/musl/include/fcntl.h#L58-L60
67-
F_RDLCK: 0,
68-
F_WRLCK: 1,
69-
F_UNLCK: 2,
70-
// From:
71-
// https://github.com/emscripten-core/emscripten/blob/81bbaa42a7827d88a71bd89701245052c622428c/system/lib/libc/musl/include/sys/file.h#L7-L10
72-
LOCK_SH: 1,
73-
LOCK_EX: 2,
74-
LOCK_NB: 4, // Non-blocking lock
75-
LOCK_UN: 8, // Unlock
76-
},
77-
errnoCodes: ERRNO_CODES,
78-
memory: {
79-
HEAP8,
80-
HEAPU8,
81-
HEAP16,
82-
HEAPU16,
83-
HEAP32,
84-
HEAPU32,
85-
HEAPF32,
86-
HEAP64,
87-
HEAPU64,
88-
HEAPF64,
89-
},
90-
wasmImports,
91-
wasmExports,
92-
syscalls: SYSCALLS,
93-
FS: typeof Emscripten.FS,
94-
PROXYFS,
95-
NODEFS,
31+
init: function () {
32+
// TODO: Move this to a library function that is made an onInit callback by the `__postset` suffix.
33+
if (PHPLoader.bindUserSpace) {
34+
/**
35+
* We need to add an onInit callback to bind the user-space API
36+
* because some dependencies like wasmImports and wasmExports
37+
* are not yet assigned.
38+
*/
39+
addOnInit(() => {
40+
Module['userSpace'] = PHPLoader.bindUserSpace({
41+
// TODO: Require PID instead of defaulting to 42.
42+
pid: PHPLoader.processId ?? 42,
43+
// TODO: When receiving this context, validate that all these fields exist.
44+
constants: {
45+
F_GETFL: Number('{{{cDefs.F_GETFL}}}'),
46+
O_ACCMODE: Number('{{{cDefs.O_ACCMODE}}}'),
47+
O_RDONLY: Number('{{{cDefs.O_RDONLY}}}'),
48+
O_WRONLY: Number('{{{cDefs.O_WRONLY}}}'),
49+
O_APPEND: Number('{{{cDefs.O_APPEND}}}'),
50+
O_NONBLOCK: Number('{{{cDefs.O_NONBLOCK}}}'),
51+
F_SETFL: Number('{{{cDefs.F_SETFL}}}'),
52+
F_GETLK: Number('{{{cDefs.F_GETLK}}}'),
53+
F_SETLK: Number('{{{cDefs.F_SETLK}}}'),
54+
F_SETLKW: Number('{{{cDefs.F_SETLKW}}}'),
55+
SEEK_SET: Number('{{{cDefs.SEEK_SET}}}'),
56+
SEEK_CUR: Number('{{{cDefs.SEEK_CUR}}}'),
57+
SEEK_END: Number('{{{cDefs.SEEK_END}}}'),
58+
F_GETFL: Number('{{{cDefs.F_GETFL}}}'),
59+
O_ACCMODE: Number('{{{cDefs.O_ACCMODE}}}'),
60+
O_RDONLY: Number('{{{cDefs.O_RDONLY}}}'),
61+
O_WRONLY: Number('{{{cDefs.O_WRONLY}}}'),
62+
O_APPEND: Number('{{{cDefs.O_APPEND}}}'),
63+
O_NONBLOCK: Number('{{{cDefs.O_NONBLOCK}}}'),
64+
F_SETFL: Number('{{{cDefs.F_SETFL}}}'),
65+
F_GETLK: Number('{{{cDefs.F_GETLK}}}'),
66+
F_SETLK: Number('{{{cDefs.F_SETLK}}}'),
67+
F_SETLKW: Number('{{{cDefs.F_SETLKW}}}'),
68+
SEEK_SET: Number('{{{cDefs.SEEK_SET}}}'),
69+
SEEK_CUR: Number('{{{cDefs.SEEK_CUR}}}'),
70+
SEEK_END: Number('{{{cDefs.SEEK_END}}}'),
71+
// From:
72+
// https://github.com/emscripten-core/emscripten/blob/66d2137b0381ac35f7e2346b2d6a90abd0f1211a/system/lib/libc/musl/include/fcntl.h#L58-L60
73+
F_RDLCK: 0,
74+
F_WRLCK: 1,
75+
F_UNLCK: 2,
76+
// From:
77+
// https://github.com/emscripten-core/emscripten/blob/81bbaa42a7827d88a71bd89701245052c622428c/system/lib/libc/musl/include/sys/file.h#L7-L10
78+
LOCK_SH: 1,
79+
LOCK_EX: 2,
80+
LOCK_NB: 4, // Non-blocking lock
81+
LOCK_UN: 8, // Unlock
82+
},
83+
errnoCodes: ERRNO_CODES,
84+
memory: {
85+
HEAP8,
86+
HEAPU8,
87+
HEAP16,
88+
HEAPU16,
89+
HEAP32,
90+
HEAPU32,
91+
HEAPF32,
92+
HEAP64,
93+
HEAPU64,
94+
HEAPF64,
95+
},
96+
wasmImports,
97+
wasmExports,
98+
syscalls: SYSCALLS,
99+
FS,
100+
PROXYFS,
101+
NODEFS,
102+
});
96103
});
97104
}
98105

@@ -114,10 +121,10 @@ const LibraryExample = {
114121
// and contains the php.ini, constants definitions, etc.
115122
FS.mkdir('/internal');
116123

117-
if (phpWasmInitOptions?.nativeInternalDirPath) {
124+
if (PHPLoader.nativeInternalDirPath) {
118125
FS.mount(
119126
FS.filesystems.NODEFS,
120-
{ root: phpWasmInitOptions.nativeInternalDirPath },
127+
{ root: PHPLoader.nativeInternalDirPath },
121128
'/internal'
122129
);
123130
}

packages/php-wasm/node/src/lib/load-runtime.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@ import type {
44
PHPRuntime,
55
OSUserSpaceAPI,
66
OSUserSpaceContext,
7+
FileLockManager,
8+
RemoteAPI,
79
} from '@php-wasm/universal';
8-
import { loadPHPRuntime, FSHelpers } from '@php-wasm/universal';
10+
import { loadPHPRuntime, FSHelpers, bindUserSpace } from '@php-wasm/universal';
911
import fs from 'fs';
1012
import { getPHPLoaderModule } from '.';
1113
import { withNetworking } from './networking/with-networking';
1214
import { withXdebug, type XdebugOptions } from './xdebug/with-xdebug';
1315
import { withIntl } from './extensions/intl/with-intl';
14-
import { joinPaths } from '@php-wasm/util';
16+
import { joinPaths, type Promised } from '@php-wasm/util';
1517
import { dirname } from 'path';
1618

1719
export interface PHPLoaderOptions {
@@ -23,6 +25,21 @@ export interface PHPLoaderOptions {
2325
}
2426

2527
type PHPLoaderOptionsForNode = PHPLoaderOptions & {
28+
/**
29+
* An optional file lock manager to use for the PHP runtime.
30+
*
31+
* The lock manager is optional when running a single php-wasm process.
32+
*
33+
* When running with JSPI, both synchronous and asynchronous
34+
* file lock managers are supported.
35+
* When running with Asyncify, the file lock manager must be synchronous.
36+
*/
37+
fileLockManager?:
38+
| RemoteAPI<FileLockManager>
39+
// Allow promised type for testing without providing true RemoteAPI.
40+
| Promised<FileLockManager>
41+
| FileLockManager;
42+
2643
emscriptenOptions?: EmscriptenOptions & {
2744
/**
2845
* The process ID for the PHP runtime.
@@ -34,21 +51,10 @@ type PHPLoaderOptionsForNode = PHPLoaderOptions & {
3451
*/
3552
processId?: number;
3653

37-
// TODO: Remove this.
38-
// /**
39-
// * An optional file lock manager to use for the PHP runtime.
40-
// *
41-
// * The lock manager is optional when running a single php-wasm process.
42-
// *
43-
// * When running with JSPI, both synchronous and asynchronous
44-
// * file lock managers are supported.
45-
// * When running with Asyncify, the file lock manager must be synchronous.
46-
// */
47-
// fileLockManager?:
48-
// | RemoteAPI<FileLockManager>
49-
// // Allow promised type for testing without providing true RemoteAPI.
50-
// | Promised<FileLockManager>
51-
// | FileLockManager;
54+
// TODO: Document this.
55+
bindUserSpace?: (
56+
userSpaceContext: OSUserSpaceContext
57+
) => OSUserSpaceAPI;
5258

5359
/**
5460
* An optional function to collect trace messages.
@@ -60,20 +66,10 @@ type PHPLoaderOptionsForNode = PHPLoaderOptions & {
6066
trace?: (processId: number, format: string, ...args: any[]) => void;
6167

6268
/**
63-
* An optional object to pass to the PHP-WASM library's `init` function.
64-
*
65-
* phpWasmInitOptions.nativeInternalDirPath is used to mount a
66-
* real, native directory as the php-wasm /internal directory.
67-
*
68-
* @see https://github.com/php-wasm/php-wasm/blob/main/compile/php/phpwasm-emscripten-library.js#L100
69+
* An optional path used to a real, native directory
70+
* to be mounted as the php-wasm /internal directory.
6971
*/
70-
phpWasmInitOptions?: {
71-
nativeInternalDirPath?: string;
72-
// TODO: Document this.
73-
bindUserSpace?: (
74-
userSpaceContext: OSUserSpaceContext
75-
) => OSUserSpaceAPI;
76-
};
72+
nativeInternalDirPath?: string;
7773
};
7874
};
7975

@@ -99,6 +95,14 @@ export async function loadNodeRuntime(
9995
quit: function (code, error) {
10096
throw error;
10197
},
98+
bindUserSpace: (userSpaceContext: OSUserSpaceContext) => {
99+
return bindUserSpace(
100+
{
101+
fileLockManager: options?.fileLockManager,
102+
},
103+
userSpaceContext
104+
);
105+
},
102106
...(options.emscriptenOptions || {}),
103107
onRuntimeInitialized: (phpRuntime: PHPRuntime) => {
104108
/**

packages/php-wasm/node/src/test/rotate-php-runtime.spec.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,14 @@ describe.each([true, false])(
2828
) =>
2929
await loadNodeRuntime(phpVersion, {
3030
emscriptenOptions: {
31-
phpWasmInitOptions: {
32-
/**
33-
* Test both with a natively mounted /internal directory, which
34-
* is what Playground CLI typically does, and without it, which
35-
* is what playground.wordpress.net does.
36-
*/
37-
nativeInternalDirPath: withNativeInternalDir
38-
? nativeInternalDirPath
39-
: undefined,
40-
},
31+
/**
32+
* Test both with a natively mounted /internal directory, which
33+
* is what Playground CLI typically does, and without it, which
34+
* is what playground.wordpress.net does.
35+
*/
36+
nativeInternalDirPath: withNativeInternalDir
37+
? nativeInternalDirPath
38+
: undefined,
4139
},
4240
});
4341
});

packages/php-wasm/universal/src/lib/os-kernel-space.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export class OSKernelSpace {
99
| RemoteAPI<FileLockManager>
1010
// Allow promised type for testing without providing true RemoteAPI.
1111
| Promised<FileLockManager>
12-
| FileLockManager;
12+
| FileLockManager
13+
| undefined;
1314

1415
constructor(fileLockManager: FileLockManager) {
1516
this.fileLockManager = fileLockManager;

packages/php-wasm/universal/src/lib/os-user-space.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,14 @@ export function bindUserSpace(
421421
async function fcntl64(fd: number, cmd: number, varargs?: number) {
422422
switch (cmd) {
423423
case F_GETLK: {
424+
const reportUnlockedFileByDefault =
425+
function reportUnlockedFileByDefault() {
426+
update_flock_struct(flockStructAddr, {
427+
l_type: F_UNLCK,
428+
});
429+
return 0;
430+
};
431+
424432
js_wasm_trace('fcntl(%d, F_GETLK)', fd);
425433
const [vfsPath, vfsPathErrno] =
426434
locking.get_vfs_path_from_fd(fd);
@@ -437,7 +445,10 @@ export function bindUserSpace(
437445
const varArgsAccessor = new VarArgsAccessor(varargs!);
438446
const flockStructAddr = varArgsAccessor.getNextAsPointer();
439447

440-
if (!locking.is_path_to_shared_fs(vfsPath)) {
448+
if (
449+
!locking.is_path_to_shared_fs(vfsPath) ||
450+
fileLockManager === undefined
451+
) {
441452
js_wasm_trace(
442453
"fcntl(%d, F_GETLK) locking is not implemented for non-NodeFS path '%s'",
443454
fd,
@@ -446,10 +457,7 @@ export function bindUserSpace(
446457

447458
// If not a NodeFS path, we can't lock it.
448459
// Default to succeeding as Emscripten does.
449-
update_flock_struct(flockStructAddr, {
450-
l_type: F_UNLCK,
451-
});
452-
return 0;
460+
return reportUnlockedFileByDefault();
453461
}
454462

455463
const flockStruct = read_flock_struct(flockStructAddr);

0 commit comments

Comments
 (0)