From a7f9328c4b09c0b004b1046de5f6a6c7096a828e Mon Sep 17 00:00:00 2001 From: Manuele Conti Date: Tue, 24 Mar 2026 09:32:05 +0100 Subject: [PATCH 1/3] Fix debugger upload path for C/C++ function blocks When debugger MD5 verification failed and the user chose to upload the current project, the UI called runCompileProgram with the raw project data instead of the preprocessed project data. That bypassed preprocessPous() for the second compilation path, so C/C++ function block bodies were sent through the IEC ST/XML pipeline as plain source code. In practice this produced a different second source set and caused iec2c to fail on invalid IL/ST instructions such as C comments, #include directives, and setup()/loop() declarations. This change applies the same preprocessPous() step used by the normal compile and debug flows before invoking runCompileProgram from the debugger mismatch flow, and aborts early if C/C++ validation fails. --- .../_organisms/workspace-activity-bar/default.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/renderer/components/_organisms/workspace-activity-bar/default.tsx b/src/renderer/components/_organisms/workspace-activity-bar/default.tsx index 7c24c7019..608b1e1d6 100644 --- a/src/renderer/components/_organisms/workspace-activity-bar/default.tsx +++ b/src/renderer/components/_organisms/workspace-activity-bar/default.tsx @@ -894,9 +894,19 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa const boardCore = availableBoards.get(boardTarget)?.core || null const runtimeJwtToken = useOpenPLCStore.getState().runtimeConnection.jwtToken || null + const { projectData: processedProjectData, validationFailed } = preprocessPous( + projectData, + isSimulatorTarget(currentBoardInfo), + (level, message) => consoleActions.addLog({ id: crypto.randomUUID(), level, message }), + ) + + if (validationFailed) { + setIsDebuggerProcessing(false) + return + } window.bridge.runCompileProgram( - [projectPath, boardTarget, boardCore, false, projectData, targetIpAddress ?? '', runtimeJwtToken], + [projectPath, boardTarget, boardCore, false, processedProjectData, targetIpAddress ?? '', runtimeJwtToken], (data: { logLevel?: 'info' | 'error' | 'warning' message: string | Buffer From 1a838599e432a7c736c578e06ff289538550b423 Mon Sep 17 00:00:00 2001 From: Manuele Conti Date: Wed, 1 Apr 2026 23:59:00 +0200 Subject: [PATCH 2/3] refactor debugger compile preparation --- .../workspace-activity-bar/default.tsx | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/src/renderer/components/_organisms/workspace-activity-bar/default.tsx b/src/renderer/components/_organisms/workspace-activity-bar/default.tsx index 608b1e1d6..afd2ad5c4 100644 --- a/src/renderer/components/_organisms/workspace-activity-bar/default.tsx +++ b/src/renderer/components/_organisms/workspace-activity-bar/default.tsx @@ -87,6 +87,12 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa const currentBoardInfo = availableBoards.get(deviceDefinitions.configuration.deviceBoard) const isCurrentBoardSimulator = isSimulatorTarget(currentBoardInfo) + const prepareProjectForCompile = () => { + return preprocessPous(projectData, isCurrentBoardSimulator, (level, message) => + addLog({ id: crypto.randomUUID(), level, message }), + ) + } + // Sync simulatorRunning when the main process stops the simulator // (e.g. on project open/create) so the UI reflects the actual state. useEffect(() => { @@ -105,11 +111,7 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa const handleRequest = () => { const boardCore = availableBoards.get(deviceDefinitions.configuration.deviceBoard)?.core || null - const { projectData: processedProjectData, validationFailed } = preprocessPous( - projectData, - isCurrentBoardSimulator, - (level, message) => addLog({ id: crypto.randomUUID(), level, message }), - ) + const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile() if (validationFailed) { setIsCompiling(false) return @@ -577,11 +579,7 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa message: 'Starting debug compilation...', }) - const { projectData: processedProjectData, validationFailed } = preprocessPous( - projectData, - isSimulatorTarget(currentBoardInfo), - (level, message) => consoleActions.addLog({ id: crypto.randomUUID(), level, message }), - ) + const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile() if (validationFailed) { setIsDebuggerProcessing(false) return @@ -894,11 +892,7 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa const boardCore = availableBoards.get(boardTarget)?.core || null const runtimeJwtToken = useOpenPLCStore.getState().runtimeConnection.jwtToken || null - const { projectData: processedProjectData, validationFailed } = preprocessPous( - projectData, - isSimulatorTarget(currentBoardInfo), - (level, message) => consoleActions.addLog({ id: crypto.randomUUID(), level, message }), - ) + const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile() if (validationFailed) { setIsDebuggerProcessing(false) From 70e090fa79cad8aec910118c3af6ecd93010620d Mon Sep 17 00:00:00 2001 From: Manuele Conti Date: Sun, 5 Apr 2026 20:02:42 +0200 Subject: [PATCH 3/3] use fresh project data in debugger upload flow --- .../_organisms/workspace-activity-bar/default.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/renderer/components/_organisms/workspace-activity-bar/default.tsx b/src/renderer/components/_organisms/workspace-activity-bar/default.tsx index afd2ad5c4..044b90225 100644 --- a/src/renderer/components/_organisms/workspace-activity-bar/default.tsx +++ b/src/renderer/components/_organisms/workspace-activity-bar/default.tsx @@ -9,6 +9,7 @@ import { connectAndActivateDebugger, disconnectDebugger, } from '@root/renderer/utils/debugger-session' +import type { PLCProjectData } from '@root/types/PLC/project/data' import type { DebugTreeNode } from '@root/types/debugger' import { BufferToStringArray, cn, isOpenPLCRuntimeTarget, isSimulatorTarget } from '@root/utils' import { parseDebugFile } from '@root/utils/debug-parser' @@ -87,8 +88,8 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa const currentBoardInfo = availableBoards.get(deviceDefinitions.configuration.deviceBoard) const isCurrentBoardSimulator = isSimulatorTarget(currentBoardInfo) - const prepareProjectForCompile = () => { - return preprocessPous(projectData, isCurrentBoardSimulator, (level, message) => + const prepareProjectForCompile = (data: PLCProjectData) => { + return preprocessPous(data, isCurrentBoardSimulator, (level, message) => addLog({ id: crypto.randomUUID(), level, message }), ) } @@ -111,7 +112,7 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa const handleRequest = () => { const boardCore = availableBoards.get(deviceDefinitions.configuration.deviceBoard)?.core || null - const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile() + const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile(projectData) if (validationFailed) { setIsCompiling(false) return @@ -579,7 +580,7 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa message: 'Starting debug compilation...', }) - const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile() + const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile(projectData) if (validationFailed) { setIsDebuggerProcessing(false) return @@ -890,9 +891,10 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa message: 'Uploading program to target...', }) + const latestProjectData = useOpenPLCStore.getState().project.data const boardCore = availableBoards.get(boardTarget)?.core || null const runtimeJwtToken = useOpenPLCStore.getState().runtimeConnection.jwtToken || null - const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile() + const { projectData: processedProjectData, validationFailed } = prepareProjectForCompile(latestProjectData) if (validationFailed) { setIsDebuggerProcessing(false)