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());
+ });
+
});