Skip to content

Commit a2f2c83

Browse files
authored
T1328518 - Scrollable - Simulated scrolling breaks after an unhandled JavaScript exception (#33572)
1 parent d246121 commit a2f2c83

2 files changed

Lines changed: 102 additions & 1 deletion

File tree

packages/devextreme/js/__internal/ui/scroll_view/scrollable.simulated.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { getHeight, getWidth } from '@js/core/utils/size';
2929
import { isDefined } from '@js/core/utils/type';
3030
import { getWindow, hasWindow } from '@js/core/utils/window';
3131
import type { ScrollEvent } from '@js/ui/scroll_view';
32+
import { logger } from '@ts/core/utils/m_console';
3233
import type { ActionConfig } from '@ts/core/widget/component';
3334
import Animator from '@ts/ui/scroll_view/animator';
3435
import type { ScrollViewScroller } from '@ts/ui/scroll_view/scroll_view.simulated';
@@ -1094,7 +1095,11 @@ export class SimulatedStrategy<
10941095
const actionHandler = this._createActionByOption(optionName);
10951096

10961097
return (...args: unknown[]) => {
1097-
actionHandler(extend(this._createActionArgs(), args));
1098+
try {
1099+
actionHandler(extend(this._createActionArgs(), args));
1100+
} catch (e) {
1101+
logger.error(e);
1102+
}
10981103
};
10991104
}
11001105

packages/devextreme/testing/tests/DevExpress.ui.widgets/scrollableParts/scrollable.actions.tests.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,3 +404,99 @@ QUnit.test('update', function(assert) {
404404
.move(0, moveDistance)
405405
.up();
406406
});
407+
408+
QUnit.module('actions stay functional after callback errors', moduleConfig);
409+
410+
[
411+
{
412+
callbackName: 'onScroll',
413+
message: 'onScroll error does not break subsequent actions',
414+
configure: function(callback) {
415+
const $scrollable = $('#scrollable').dxScrollable({
416+
useNative: false,
417+
inertiaEnabled: false,
418+
bounceEnabled: false,
419+
onScroll: callback,
420+
});
421+
422+
return {
423+
trigger: function() {
424+
pointerMock($scrollable.find('.' + SCROLLABLE_CONTENT_CLASS))
425+
.start()
426+
.down()
427+
.move(0, -10)
428+
.up();
429+
},
430+
};
431+
},
432+
},
433+
{
434+
callbackName: 'onUpdated',
435+
message: 'onUpdated error does not break subsequent actions',
436+
configure: function(callback) {
437+
const scrollable = $('#scrollable').dxScrollable({
438+
useNative: false,
439+
onUpdated: callback,
440+
}).dxScrollable('instance');
441+
442+
return {
443+
trigger: function() {
444+
scrollable.update();
445+
},
446+
};
447+
},
448+
},
449+
{
450+
callbackName: 'onStart',
451+
message: 'onStart error does not break subsequent actions',
452+
configure: function(callback) {
453+
const scrollable = $('#scrollable').dxScrollable({
454+
useNative: false,
455+
onStart: callback,
456+
}).dxScrollable('instance');
457+
458+
return {
459+
trigger: function() {
460+
scrollable.scrollBy({ top: 10 });
461+
},
462+
};
463+
},
464+
},
465+
{
466+
callbackName: 'onEnd',
467+
message: 'onEnd error does not break subsequent actions',
468+
configure: function(callback) {
469+
const scrollable = $('#scrollable').dxScrollable({
470+
useNative: false,
471+
onEnd: callback,
472+
}).dxScrollable('instance');
473+
474+
return {
475+
trigger: function() {
476+
scrollable.scrollBy({ top: 10 });
477+
},
478+
};
479+
},
480+
},
481+
].forEach((testCase) => {
482+
QUnit.test(testCase.message, function(assert) {
483+
let callbackCallCount = 0;
484+
485+
const { trigger } = testCase.configure(function() {
486+
callbackCallCount++;
487+
throw new Error(testCase.callbackName + ' error');
488+
});
489+
490+
callbackCallCount = 0;
491+
492+
trigger();
493+
trigger();
494+
495+
assert.strictEqual(
496+
callbackCallCount,
497+
2,
498+
`${testCase.callbackName}: component remained functional and handled both actions after callback errors`,
499+
);
500+
});
501+
});
502+

0 commit comments

Comments
 (0)