Описание
Оператор ДобавитьОбработчик, выполненный внутри #native-модуля, не создаёт подписку
на событие. Ни ошибки компиляции, ни исключения в рантайме — обработчик просто никогда
не вызывается.
То же и с УдалитьОбработчик.
Это опаснее падения: код компилируется, выполняется, выглядит рабочим, но ведёт себя
иначе, чем в стековом режиме.
Воспроизведение
Источник события, Классы/ИсточникСобытия.os (стековый):
Процедура Стрельнуть() Экспорт
ВызватьСобытие("Событие", Новый Массив());
КонецПроцедуры
Процедура Событие() Экспорт
КонецПроцедуры
Процедура ПриСозданииОбъекта()
КонецПроцедуры
Подписчик, Классы/Подписчик.os — считает вызовы:
Перем Вызовов Экспорт;
Процедура Обработчик() Экспорт
Вызовов = Вызовов + 1;
КонецПроцедуры
Процедура ПриСозданииОбъекта()
Вызовов = 0;
КонецПроцедуры
Два подписывателя, различаются ровно одной директивой.
Классы/ПодписывательСтековый.os:
Процедура Подписать(Источник, Подписчик) Экспорт
ДобавитьОбработчик Источник.Событие, Подписчик.Обработчик;
КонецПроцедуры
Процедура ПриСозданииОбъекта()
КонецПроцедуры
Классы/ПодписывательНативный.os:
#native
Процедура Подписать(Источник, Подписчик) Экспорт
ДобавитьОбработчик Источник.Событие, Подписчик.Обработчик;
КонецПроцедуры
Процедура ПриСозданииОбъекта()
КонецПроцедуры
Сценарий запуска:
#Использовать "."
Процедура Проверить(Имя, Подписыватель, Подписчик)
Источник = Новый ИсточникСобытия();
Подписыватель.Подписать(Источник, Подписчик);
Источник.Стрельнуть();
Сообщить(Имя + ": вызовов обработчика = " + Подписчик.Вызовов);
КонецПроцедуры
Проверить("стек-подписыватель ", Новый ПодписывательСтековый(), Новый Подписчик());
Проверить("native-подписыватель", Новый ПодписывательНативный(), Новый Подписчик());
Фактическое поведение
стек-подписыватель : вызовов обработчика = 1
native-подписыватель: вызовов обработчика = 0
Режим модуля подписчика на результат не влияет — важен только режим того модуля,
в котором выполняется сам оператор ДобавитьОбработчик:
стек-подписыватель + стек-подписчик : вызовов обработчика = 1
стек-подписыватель + native-подписчик : вызовов обработчика = 1
native-подписыватель + стек-подписчик : вызовов обработчика = 0
native-подписыватель + native-подписчик : вызовов обработчика = 0
Ожидаемое поведение
вызовов обработчика = 1 во всех четырёх сочетаниях. Если подписка из native
не поддерживается — нужна ошибка компиляции, а не тихий no-op.
Окружение
Воспроизводится одинаково на:
- 2.2.0, linux-x64
- 2.3.0-dev+6 (ночная сборка), linux-x64
Влияние
В autumn после перевода класса-сканера
на #native беззвучно отключилась вся валидация компонентов: приемки перестали
получать события фабрики. Компиляция прошла, приложение запустилось, ошибок нет —
поймали только по упавшему тесту, который проверял, что некорректный компонент
вызывает исключение.
Обход есть: вынести ДобавитьОбработчик/УдалитьОбработчик в отдельный стековый
класс-помощник и делегировать подписку ему.
Описание
Оператор
ДобавитьОбработчик, выполненный внутри#native-модуля, не создаёт подпискуна событие. Ни ошибки компиляции, ни исключения в рантайме — обработчик просто никогда
не вызывается.
То же и с
УдалитьОбработчик.Это опаснее падения: код компилируется, выполняется, выглядит рабочим, но ведёт себя
иначе, чем в стековом режиме.
Воспроизведение
Источник события,
Классы/ИсточникСобытия.os(стековый):Подписчик,
Классы/Подписчик.os— считает вызовы:Два подписывателя, различаются ровно одной директивой.
Классы/ПодписывательСтековый.os:Классы/ПодписывательНативный.os:Сценарий запуска:
Фактическое поведение
Режим модуля подписчика на результат не влияет — важен только режим того модуля,
в котором выполняется сам оператор
ДобавитьОбработчик:Ожидаемое поведение
вызовов обработчика = 1во всех четырёх сочетаниях. Если подписка из nativeне поддерживается — нужна ошибка компиляции, а не тихий no-op.
Окружение
Воспроизводится одинаково на:
Влияние
В autumn после перевода класса-сканера
на
#nativeбеззвучно отключилась вся валидация компонентов: приемки пересталиполучать события фабрики. Компиляция прошла, приложение запустилось, ошибок нет —
поймали только по упавшему тесту, который проверял, что некорректный компонент
вызывает исключение.
Обход есть: вынести
ДобавитьОбработчик/УдалитьОбработчикв отдельный стековыйкласс-помощник и делегировать подписку ему.