Ban proc_open() and exec() entirely - replace with shell_exec() and file redirection
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -82,69 +82,37 @@ class JqhtmlWebpackCompiler
|
||||
// Execute official CLI compiler with IIFE format for self-registering templates
|
||||
// CRITICAL: Must include --sourcemap for proper error mapping in bundles
|
||||
// JQHTML v2.2.65+ uses Mozilla source-map library for reliable concatenation
|
||||
// IMPORTANT: Using proc_open() instead of \exec_safe() to handle large template outputs
|
||||
// \exec_safe() can truncate output for complex templates due to line-by-line buffering
|
||||
// IMPORTANT: Using file redirection instead of proc_open() to avoid pipe buffer truncation
|
||||
// proc_open() has race conditions with feof() that cause silent data loss on large outputs (35KB+)
|
||||
|
||||
// Generate temp file for output
|
||||
$temp_file = storage_path('rsx-tmp/jqhtml_compile_' . uniqid() . '.js');
|
||||
|
||||
// Redirect stdout to file, stderr to stdout for error capture, then echo exit code
|
||||
$command = sprintf(
|
||||
'%s compile %s --format iife --sourcemap',
|
||||
'%s compile %s --format iife --sourcemap > %s 2>&1; echo $?',
|
||||
escapeshellarg($this->compiler_path),
|
||||
escapeshellarg($file_path)
|
||||
escapeshellarg($file_path),
|
||||
escapeshellarg($temp_file)
|
||||
);
|
||||
|
||||
$descriptors = [
|
||||
0 => ['pipe', 'r'], // stdin
|
||||
1 => ['pipe', 'w'], // stdout
|
||||
2 => ['pipe', 'w'] // stderr
|
||||
];
|
||||
// Execute command synchronously - shell_exec captures the exit code from echo $?
|
||||
$result = shell_exec($command);
|
||||
$return_code = (int)trim($result);
|
||||
|
||||
$process = proc_open($command, $descriptors, $pipes);
|
||||
|
||||
if (!is_resource($process)) {
|
||||
throw new \RuntimeException("Failed to execute jqhtml compiler");
|
||||
// Read the compiled output from file
|
||||
$compiled_js = '';
|
||||
if (file_exists($temp_file)) {
|
||||
$compiled_js = file_get_contents($temp_file);
|
||||
unlink($temp_file); // Clean up temp file
|
||||
}
|
||||
|
||||
// Close stdin
|
||||
fclose($pipes[0]);
|
||||
|
||||
// Set blocking mode to ensure complete reads
|
||||
stream_set_blocking($pipes[1], true);
|
||||
stream_set_blocking($pipes[2], true);
|
||||
|
||||
// Read stdout and stderr completely in chunks
|
||||
// CRITICAL: Use feof() as loop condition to prevent race condition truncation
|
||||
// Checking feof() AFTER empty reads can cause 8192-byte truncation bug
|
||||
$output_str = '';
|
||||
$error_str = '';
|
||||
|
||||
// Read stdout until EOF
|
||||
while (!feof($pipes[1])) {
|
||||
$chunk = fread($pipes[1], 8192);
|
||||
if ($chunk !== false) {
|
||||
$output_str .= $chunk;
|
||||
}
|
||||
}
|
||||
|
||||
// Read stderr until EOF
|
||||
while (!feof($pipes[2])) {
|
||||
$chunk = fread($pipes[2], 8192);
|
||||
if ($chunk !== false) {
|
||||
$error_str .= $chunk;
|
||||
}
|
||||
}
|
||||
|
||||
fclose($pipes[1]);
|
||||
fclose($pipes[2]);
|
||||
|
||||
// Get return code
|
||||
$return_code = proc_close($process);
|
||||
|
||||
// Combine stdout and stderr for error messages
|
||||
if ($return_code !== 0 && !empty($error_str)) {
|
||||
$output_str = $error_str . "\n" . $output_str;
|
||||
}
|
||||
// If there was an error, the output file will contain the error message
|
||||
$output_str = $compiled_js;
|
||||
|
||||
// Check for compilation errors
|
||||
if ($return_code !== 0) {
|
||||
// Official CLI outputs errors to stderr (captured in stdout with 2>&1)
|
||||
// Error output captured in output_str via 2>&1 redirection
|
||||
// Try multiple error formats
|
||||
|
||||
// Format 1: "at filename:line:column" (newer format)
|
||||
@@ -179,8 +147,7 @@ class JqhtmlWebpackCompiler
|
||||
);
|
||||
}
|
||||
|
||||
// Success - the output is the compiled JavaScript
|
||||
$compiled_js = $output_str;
|
||||
// Success - compiled_js already contains the output from the temp file
|
||||
|
||||
// Don't add any comments - they break sourcemap line offsets
|
||||
// Just use the compiler output as-is
|
||||
|
||||
Reference in New Issue
Block a user