From 9b607bd0432ec9054bb739e4ecf02d17d150af56 Mon Sep 17 00:00:00 2001 From: Daniel <150448993+sombrek@users.noreply.github.com> Date: Mon, 7 Oct 2024 16:59:55 +0200 Subject: [PATCH] fix: allow errors to propagate upwards Closes #187 --- lib/simulator/behaviors/EventBehaviors.js | 31 ++++- ....error-catch-all-outer-event-sub-none.bpmn | 86 ++++++++++++++ ....error-catch-all-outer-event-sub-none.json | 44 +++++++ ...r.error-catch-all-outer-event-sub-ref.bpmn | 112 ++++++++++++++++++ ...r.error-catch-all-outer-event-sub-ref.json | 44 +++++++ test/spec/simulator/SimulatorSpec.js | 24 ++++ 6 files changed, 335 insertions(+), 6 deletions(-) create mode 100644 test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.bpmn create mode 100644 test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.json create mode 100644 test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.bpmn create mode 100644 test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.json diff --git a/lib/simulator/behaviors/EventBehaviors.js b/lib/simulator/behaviors/EventBehaviors.js index 9e0b64f0..a825b38b 100644 --- a/lib/simulator/behaviors/EventBehaviors.js +++ b/lib/simulator/behaviors/EventBehaviors.js @@ -131,21 +131,40 @@ EventBehaviors.prototype.get = function(element) { 'bpmn:ErrorEventDefinition': (context) => { - // HINT: errors are handled in current scope only (does not bubble) + // HINT: errors are propagated up the scope + // chain and caught by the first matching boundary event + // or event sub-process const { element, scope } = context; + const scopes = this._simulator.findScopes({ + subscribedTo: { + event: element + }, + trait: ScopeTraits.ACTIVE + }); + + let triggerScope = scope; + // TODO(nikku): ensure error always interrupts, also if no error // catch is present - this._simulator.trigger({ - event: element, - initiator: scope, - scope: findSubscriptionScope(scope) - }); + while ((triggerScope = triggerScope.parent)) { + + if (scopes.includes(triggerScope)) { + this._simulator.trigger({ + event: element, + scope: triggerScope, + initiator: scope + }); + + break; + } + } }, + 'bpmn:TerminateEventDefinition': (context) => { const { scope diff --git a/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.bpmn b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.bpmn new file mode 100644 index 00000000..45ec58b2 --- /dev/null +++ b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.bpmn @@ -0,0 +1,86 @@ + + + + + Flow_1 + + + Flow_1 + Flow_4 + + Flow_2 + + + + Flow_2 + + + + + + Flow_4 + + + + + Flow_7 + + + + Flow_7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.json b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.json new file mode 100644 index 00000000..ac4afcc7 --- /dev/null +++ b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-none.json @@ -0,0 +1,44 @@ +[ + "createScope:Process_1:null", + "signal:Process_1:B", + "createScope:StartEvent_1:B", + "signal:StartEvent_1:C", + "exit:StartEvent_1:C", + "createScope:Flow_1:B", + "destroyScope:StartEvent_1:C", + "enter:Flow_1:B", + "exit:Flow_1:D", + "createScope:SubProcess:B", + "destroyScope:Flow_1:D", + "enter:SubProcess:B", + "createScope:StartEvent_2:E", + "signal:StartEvent_2:F", + "exit:StartEvent_2:F", + "createScope:Flow_2:E", + "destroyScope:StartEvent_2:F", + "enter:Flow_2:E", + "exit:Flow_2:G", + "createScope:ErrorEvent_1:E", + "destroyScope:Flow_2:G", + "enter:ErrorEvent_1:E", + "createScope:EventSubProcess_3:B", + "signal:EventSubProcess_3:I", + "destroyScope:ErrorEvent_1:H", + "destroyScope:SubProcess:E", + "createScope:OuterErrorStart_none:I", + "signal:OuterErrorStart_none:J", + "exit:OuterErrorStart_none:J", + "createScope:Flow_7:I", + "destroyScope:OuterErrorStart_none:J", + "enter:Flow_7:I", + "exit:Flow_7:K", + "createScope:EndEvent_5:I", + "destroyScope:Flow_7:K", + "enter:EndEvent_5:I", + "exit:EndEvent_5:L", + "destroyScope:EndEvent_5:L", + "exit:EventSubProcess_3:I", + "destroyScope:EventSubProcess_3:I", + "exit:Process_1:B", + "destroyScope:Process_1:B" +] \ No newline at end of file diff --git a/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.bpmn b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.bpmn new file mode 100644 index 00000000..d11e3071 --- /dev/null +++ b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.bpmn @@ -0,0 +1,112 @@ + + + + + Flow_1 + + + Flow_1 + Flow_4 + + Flow_2 + + + + Flow_2 + + + + + + Flow_4 + + + + + Flow_7 + + + + Flow_7 + + + + + + Flow_8 + + + + Flow_8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.json b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.json new file mode 100644 index 00000000..69dd80c2 --- /dev/null +++ b/test/spec/simulator/Simulator.error-catch-all-outer-event-sub-ref.json @@ -0,0 +1,44 @@ +[ + "createScope:Process_1:null", + "signal:Process_1:B", + "createScope:StartEvent_1:B", + "signal:StartEvent_1:C", + "exit:StartEvent_1:C", + "createScope:Flow_1:B", + "destroyScope:StartEvent_1:C", + "enter:Flow_1:B", + "exit:Flow_1:D", + "createScope:SubProcess:B", + "destroyScope:Flow_1:D", + "enter:SubProcess:B", + "createScope:StartEvent_2:E", + "signal:StartEvent_2:F", + "exit:StartEvent_2:F", + "createScope:Flow_2:E", + "destroyScope:StartEvent_2:F", + "enter:Flow_2:E", + "exit:Flow_2:G", + "createScope:ErrorEvent_1:E", + "destroyScope:Flow_2:G", + "enter:ErrorEvent_1:E", + "createScope:EventSubProcess_4:B", + "signal:EventSubProcess_4:I", + "destroyScope:ErrorEvent_1:H", + "destroyScope:SubProcess:E", + "createScope:OuterErrorStart_123:I", + "signal:OuterErrorStart_123:J", + "exit:OuterErrorStart_123:J", + "createScope:Flow_8:I", + "destroyScope:OuterErrorStart_123:J", + "enter:Flow_8:I", + "exit:Flow_8:K", + "createScope:EndEvent_6:I", + "destroyScope:Flow_8:K", + "enter:EndEvent_6:I", + "exit:EndEvent_6:L", + "destroyScope:EndEvent_6:L", + "exit:EventSubProcess_4:I", + "destroyScope:EventSubProcess_4:I", + "exit:Process_1:B", + "destroyScope:Process_1:B" +] \ No newline at end of file diff --git a/test/spec/simulator/SimulatorSpec.js b/test/spec/simulator/SimulatorSpec.js index 9c042798..e5444e47 100644 --- a/test/spec/simulator/SimulatorSpec.js +++ b/test/spec/simulator/SimulatorSpec.js @@ -1088,6 +1088,30 @@ describe('simulator', function() { expectTrace(fixture()); }); + + verify('escalation-catch-all-outer-event-sub-ref', (fixture) => { + + // when + trigger({ + element: element('StartEvent_1') + }); + + // then + expectTrace(fixture()); + }); + + + verify('escalation-catch-all-outer-event-sub-none', (fixture) => { + + // when + trigger({ + element: element('StartEvent_1') + }); + + // then + expectTrace(fixture()); + }); + });