OneScript
OneScript copied to clipboard
Ошибка при рефлексии свойств у загруженного с контекстом сценария
Опишите ошибку В случае если в сценарий, который был загружен через ЗагрузитьСценарий() с передачей во втором параметре контекст, попробую себе отрефлексировать таблицу свойств через ЭтотОбъект, будет получена ошибка:
Внешнее исключение (System.ArgumentOutOfRangeException): Индекс за пределами диапазона. Индекс должен быть положительным числом, а его размер не должен превышать размер коллекции.
Имя параметра: index}
Воспроизведение ошибки
// test.os
ЗагрузитьСценарий("./Загружаемый.os"); // Ок
Контекст = Новый Структура(
"АргументыКоманднойСтроки",
Новый Массив
);
ЗагрузитьСценарий("./Загружаемый.os", Контекст); // Ошибка
// Загружаемый.os
Рефлектор = Новый Рефлектор();
Рефлектор.ПолучитьТаблицуСвойств(
ЭтотОбъект
);
Сообщить("Ок");
oscript test.os
Ожидаемое поведение В ошибку не падает
Окружение
- ОС: Win11 23H2
- Версия: 1.9.1.80
Дополнительная информация OsReflectorBug.zip
/CC @EvilBeaver @Mr-Rm
Кажется, таких извращений рефлектор не предусматривает by design. Ну т.е. примерно понятно где ошибка, такое просто не предусмотрели.
Кажется, таких извращений рефлектор не предусматривает by design. Ну т.е. примерно понятно где ошибка, такое просто не предусмотрели.
Дык в 1.8 работало, в 1.9 сломалось
Даже так? Спасибо, посмотрю (но не знаю когда)
Падает на https://github.com/EvilBeaver/OneScript/blob/ffe8dbecd6b17b54aae7f5e391da08460b08c56b/src/ScriptEngine/Machine/IRuntimeContextInstance.cs#L78 Сломалось в 1.8.1
К @Absolemus по PR #1242
Верно ли, что Рефлектор.ПолучитьТаблицуСвойств(ЭтотОбъект,Истина); должен получать то же, что и ПолучитьТаблицуСвойств(ЭтотОбъект, Ложь), включая переданный контекст, плюс глобальные неэкспортные переменные модуля? А неглобальные?
Что-то я не помню, чтобы переданный контекст когда-то отдавался рефлектором (и не думаю, что должен). Это же просто символы, доступные для обращения, как имя модуля.
По описанию метода "ЗагрузитьСценарий", да и фактически, передаваемый контекст - это полноценный набор глобальных переменных, экспортируемых в вызывающий модуль:
Контекст = Новый Структура("Арг", 1);
ЗагрузитьСценарийИзСтроки("Арг=2;", Контекст);
Сообщить("Арг="+Контекст.Арг);
Арг=2
И это несмотря на возникающую ошибку: {Модуль <string 8A9886C3> / Ошибка в строке: 1 / Свойство недоступно для записи} Баг?
К @Absolemus по PR #1242 Верно ли, что
Рефлектор.ПолучитьТаблицуСвойств(ЭтотОбъект,Истина);должен получать то же, что иПолучитьТаблицуСвойств(ЭтотОбъект, Ложь), включая переданный контекст, плюс глобальные неэкспортные переменные модуля? А неглобальные?
По задумке - должен. Контекст это внешние видимые части объекта, как реквизиты в модуле документа, например.
По задумке - должен. Контекст это внешние видимые части объекта, как реквизиты в модуле документа, например.
А это разве не "глобальный контекст" типа как "АргументыКоманднойСтроки" ?
Передаваемый контекст перекрывает глобальный:
Контекст = Новый Структура("АргументыКоманднойСтроки", "Перекрыто!");
ЗагрузитьСценарийИзСтроки("Cообщить(АргументыКоманднойСтроки)", Контекст);
Перекрыто!
То же для , например Консоль. Но:
Контекст = Новый Структура("ЭтотОбъект", "Перекрыто!");
ЗагрузитьСценарийИзСтроки("Cообщить(ЭтотОбъект)", Контекст);
{Модуль C:_lab\OneScript\OsReflectorBug\test.os / Ошибка в строке: 2 / Внешнее исключение (System.InvalidOperationException): Symbol already defined in the scope (ЭтотОбъект)}
ЗагрузитьСценарийИзСтроки("Cообщить(ЭтотОбъект)", Контекст);
Замеченный выше баг со "Свойство недоступно для записи" воспроизвести не удалось. Значит, переданные через контекст свойства - всё же строго r/o (так ли задумывалось?)
Странное с Рефлектором:
Ст = Новый Структура("Поле1, Поле2", -1, -2);
ТСв=Рефлектор.ПолучитьТаблицуСвойств(Ст);
Сообщить("Т0:"+ТСв.Количество());
ТСв=Рефлектор.ПолучитьТаблицуСвойств(Ст, Истина); // <--
Сообщить("Т1:"+ТСв.Количество());
Т0:2
Т1:0 // ??
GetPropertiesWithPrivate и GetPropertiesWithoutPrivate сделаны существенно по-разному
Баг?
Нет. Передаваемый контекст доступен только для чтения, так и задумано.
С перекрытием то же самое, перекрывать должен, как перекрывает Перем в методе
Сейчас получается, что Рефлектор.ПолучитьТаблицуСвойств(..., Истина); возвращает только приватные свойства, а не все, включая приватные. Верно ли это? Изменение может затронуть библиотеки autumn и decorator, возможно и другие.
Исключение при попытке перекрытия ЭтотОбъект нужно более информативное.
В таблицу свойств не передаётся признак свойства о возможности записи.
Это для v1. В v2 всё реализовано и работает по-другому, в т. ч. "System.NotImplementedException" в ряде случаев
@nixel2007 @sfaqer вы основные клиенты рефлектора, подскажите, как правильно? Я полагал, что "все, включая приватные"
GetPropertiesWithPrivate и GetPropertiesWithoutPrivate сделаны существенно по-разному
@Mr-Rm там ужас что и давно бы пора навести там порядок со свойствами, полями, экспортными неэкспортными и тем, что выставляется в контекст.
@nixel2007 @sfaqer вы основные клиенты рефлектора, подскажите, как правильно? Я полагал, что "все, включая приватные"
Полагаю так же, "все включая приватные", ей богу я был уверен что оно так и работает.
Полагаю так же, "все включая приватные", ей богу я был уверен что оно так и работает.
Оно даже тестами вроде как покрыто....
Тесты покрывают не все типы объектов, а сосредоточены, в основном, на Сценариях - там всё работает. Можно, конечно, ограничить применение Рефлектора только Сценариями. Аннотаций у свойств/методов других типов не бывает.
Отмечу здесь
Ст = Новый Структура("Поле1, Поле2", -1, -2);
ТСв=Рефлектор.ПолучитьТаблицуСвойств(Ст);
Сообщить("КСт="+ТСв.Количество());
В v1 КСт=2, v2 падает с NotImplemented
ФСт = Новый ФиксированнаяСтруктура("Поле1, Поле2", -1, -2);
ТСв=Рефлектор.ПолучитьТаблицуСвойств(ФСт);
Сообщить("КФСт="+ТСв.Количество());
Обе версии показывают КФСт=0, всегда. Причина - у ФиксированнаяСтруктура нет переопределения функции GetPropCount(), а из базового DynamicPropertiesAccessor приходит 0.
(Посмотреть в других объектах)
Я от флага "включая приватные" ожидаю, что будут возвращены все, включая приватные :) В плане либ - практически все высокоуровневые либы используют Хоревский reflector, так что главное, чтобы он работал. Но выпустить фикс, конечно же, не проблема, главное понять, что там сломается. Тесты у либы тоже в избытке.
@Mr-Rm вижу коммит. Добьешь до пуллреквеста?
Для v2 сделаю, там отмеченного в начале бага нет. Но там всё через LINQ, нет ли вопросов к быстродействию рефлектора?
Для v2 сделаю, там отмеченного в начале бага нет. Но там всё через LINQ, нет ли вопросов к быстродействию рефлектора?
А Linq сильно медленнее по факту? В яве стримы, например, очень хорошо оптимизированы, я им тоже поначалу не доверял, но они реально быстрые
нет ли вопросов к быстродействию рефлектора?
А про какие конкретно операции идёт речь? У него кмк конструктор тяжеловат, или речь про что-то другое?
ПолучитьТаблицуСвойств самая тяжелая. А конструктор же почти пустой (для v2).
О конструкторе Рефлектора: нужен ли он? Не перевести ли Рефлектор в глобальный синглтон, подобно Консоль?
С консолью в прошлый раз огребли проблем. Лучше не надо пока
@Mr-Rm а эта задача закрывается реквестом #1503 или еще что-то надо будет по ней сделать после вливания реквеста?
v2 закрывается #1503, Для v1 готовится PR