Skip to content

Commit ae7033b

Browse files
committed
Narrow down the follow: false argument to php functions that call FS.stat
1 parent 706c100 commit ae7033b

File tree

1 file changed

+36
-23
lines changed

1 file changed

+36
-23
lines changed

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

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,30 +96,38 @@ export async function loadNodeRuntime(
9696
* for the path and Emscripten will accept it as if it was the real link path.
9797
*/
9898
if (options?.followSymlinks === true) {
99-
/**
100-
* By default, Emscripten will not follow symlinks when it's the final path component.
101-
* This behavior can cause issues in PHP-wasm when the caller requires the symlink to be followed,
102-
* but the PHP-wasm call to lookupPath didn't explicitly set follow to true.
103-
*
104-
* To ensure symlinks are followed by default when symlink following is enabled in PHP-wasm,
105-
* we override the `lookupPath` function and set follow to true.
106-
*
107-
* PHP and Emscripten functions can still override the default behavior
108-
* by setting follow to false which is required for function calls like lstat.
109-
*/
110-
const lookupPath = phpRuntime.FS.lookupPath;
111-
phpRuntime.FS.lookupPath = (
112-
path: string,
113-
options: any = {}
114-
) => {
115-
return lookupPath(path, {
116-
...options,
99+
const fsStat = phpRuntime.FS.stat;
100+
phpRuntime.FS.stat = (path: string, dontFollow: boolean) => {
101+
if (dontFollow === true && path.includes('woocommerce')) {
102+
const obj: any = {};
103+
if ('captureStackTrace' in Error) {
104+
Error.captureStackTrace(obj);
105+
}
106+
const stack = obj.stack.split('\n');
107+
const lastStackLine = stack[stack.length - 1];
108+
const functionName = lastStackLine.trim().split(' ')[1];
109+
117110
/**
118-
* If follow is true, a symlinked plugin will successfully be mounted during boot.
119-
* But that would break POSIX compatibility because callers need to be able to not follow symlinks.
111+
* One of these functions is called with dontFollow set to true
112+
* and causes plugin activation to fail with a "Plugin file does not exist" error.
113+
*
114+
* Potentially related to https://core.trac.wordpress.org/ticket/16953
120115
*/
121-
// follow: true,
122-
});
116+
if (
117+
[
118+
'php.wasm.php_stat',
119+
'php.wasm.__fstatat',
120+
'php.wasm.tsrm_realpath_r',
121+
].includes(functionName)
122+
) {
123+
console.log(
124+
`[DEBUG] dontFollow override for function ${functionName} for path ${path}`,
125+
obj.stack
126+
);
127+
dontFollow = false;
128+
}
129+
}
130+
return fsStat(path, dontFollow);
123131
};
124132

125133
phpRuntime.FS.filesystems.NODEFS.node_ops.readlink = (
@@ -155,7 +163,12 @@ export async function loadNodeRuntime(
155163
{ root: absoluteSourcePath },
156164
symlinkPath
157165
);
158-
console.log('\n[DEBUG] readlink mounted symlinked path', absoluteSourcePath, '->', symlinkPath);
166+
console.log(
167+
'\n[DEBUG] readlink mounted symlinked path',
168+
absoluteSourcePath,
169+
'->',
170+
symlinkPath
171+
);
159172
}
160173
return symlinkPath;
161174
};

0 commit comments

Comments
 (0)