Ember.js: Утверждение возврата с возвратом "более агрессивное" в 3.22

Созданный на 12 окт. 2020  ·  47Комментарии  ·  Источник: emberjs/ember.js

🐞 Опишите ошибку

Устаревшая функция autotracking.mutation-after-usage выдает ошибку, которая приводит к поломке приложений вместо предупреждения.

🔬 Минимальное воспроизведение

https://ember-twiddle.com/c677ed60d39938c97ea7438d177c0ef3?openFiles=controllers.application%5C.js%2C

Чтобы увидеть ошибку, нужно открыть консоль.

😕 Фактическое поведение

Прекращение поддержки вызывает ошибку

🤔 Ожидаемое поведение

Устарение - это предупреждение

🌍 Окружающая среда

  • Ember: 3.22.0
  • Node.js / npm: -
  • ОПЕРАЦИОННЫЕ СИСТЕМЫ: -
  • Браузер: -
Needs Reproduction

Самый полезный комментарий

Быстрое обновление здесь, 3.23.1 выпущена с исправлениями. Постараюсь завтра доделать 3.22.x (проблемы с подбором вишни).

Все 47 Комментарий

Хм, я не совсем понимаю, что вы здесь имеете в виду. Выдаваемая ошибка является утверждением (а не устареванием) и не предназначена для того, чтобы ее можно было обойти ...

Я сейчас закрою, но с радостью открою, если я что-то здесь неправильно понял ...

https://github.com/emberjs/ember.js/blob/c5bbf863af7cd8f6f92a97f2b777ff857bf9a9f4/packages/%40ember/-internals/glimmer/lib/environment.ts#L65

Это предполагаемое устаревание, которое должно выполняться, но почему утверждение вызывает ошибку, а не выводит предупреждение. Ошибка приводит к тому, что приложения не работают, вместо того, чтобы показывать предупреждение о необходимости рефакторинга.

Место, с которым вы связались, - это место, где Ember настраивает механизм рендеринга, он предоставляет хуки как для утверждений, так и для устаревших, а механизм рендеринга выбирает, какой из них использовать в зависимости от сценария.

Эти настроенные параметры превращаются в выполнение одного из следующих действий в glimmer-vm:


Не могли бы вы подробнее описать, почему вы думаете, что этот конкретный случай должен быть устаревшим, а не утверждением? Конкретная вещь, выполняемая в твиддле, всегда предназначалась для предотвращения (как объясняется в сообщении об ошибке):

export default class ApplicationController extends Controller {
  <strong i="18">@tracked</strong> appName = 'Ember Twiddle';

  get name() {
    this.appName = "Test"

    if (this.appName === "Test") {
      this.appName = "test"
    }

    return this.appName
  }
}

В частности, в этом случае вы читаете отслеживаемое значение, а затем обновляете его (что фактически вызовет цикл, если мы не предотвратим его с помощью этого утверждения).

@rwjblue Я думаю, что проблема здесь в том, что незначительный выпуск Ember приводит к тому, что приложения, которые ранее неосознанно нарушали это утверждение, теперь блокируются от обновления до тех пор, пока их обновления с возвратом не будут разрешены. В моем случае поддерживаемое мной приложение заблокировано от обновления до 3.22, потому что аддон, который он использует, нарушает это утверждение.

Если бы эти утверждения об обратном отслеживании были представлены в виде предупреждений, а не ошибок, это дало бы таким приложениям, как мое, более простой способ оставаться в курсе последних событий, поскольку у нас было бы время для отслеживания этих проблем. В настоящее время мое приложение должно оставаться на версии 3.21, пока у меня не будет пропускной способности, чтобы отследить, где и почему оно нарушает это новое утверждение.

Я считаю, что это ошибка, потому что ember-gestures перестали работать с Ember 3.22.
Они используют эту функцию для удаления, и она работала с предыдущими версиями.
Переменная __instance читается, а затем обновляется, так что это означает, что она больше не работает и теперь вызывает сбой приложений, даже если это не было существенным изменением версии.

  __teardownRecognizers: on('willDestroyElement', function() {
    let instance = this.get('__instance');
    if (instance) {
      //instance.off();
      instance.destroy();
      this.set('__instance', null);
    }
  }),

Я думаю, проблема здесь в том, что незначительный выпуск Ember приводит к тому, что приложения, которые ранее неосознанно нарушали это утверждение, теперь блокируются от обновления до тех пор, пока их обновления с возвратом не будут решены. В моем случае поддерживаемое мной приложение заблокировано от обновления до 3.22, потому что аддон, который он использует, нарушает это утверждение.

Отлично! В исходном отчете не указывалось, что код в твиддле действительно работал (или каких-либо объяснений того, почему это была ошибка).

@kpfefferle - С какой версии вы обновляетесь? Каков источник мутации, вызывающей такое утверждение в вашем случае?

Чтобы быть ясным, я в основном пытаюсь понять, о чем здесь сообщается (объем, шаблоны использования и т.д.), и я специально не пытаюсь рационализировать или спорить о SemVer. 😸

@rwjblue У меня есть два приложения с неудачными

        actual: >
            [object Object]
        stack: >
            Error: Assertion Failed: You attempted to update `_errors` on `changeset:[object Object]`, but it had already been used previously in the same computation.  Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.

            `_errors` was first used:

            - While rendering:
              application
                forms
                  forms.form
                    form-workflow
                      form-workflow/form
                        form-for

            Stack trace for the update:
                at setter ([...]/assets/vendor.js:56179:9)
                at EmberChangeset.set [as _errors] ([...]/assets/vendor.js:17775:7)
                at EmberChangeset.BufferedChangeset.set (webpack://__ember_auto_import__/./node_modules/validated-changeset/dist/validated-changeset.es5.js?:2674:17)
                at Object.set ([...]/assets/vendor.js:104899:22)
                at Proxy.BufferedChangeset._handleValidation (webpack://__ember_auto_import__/./node_modules/validated-changeset/dist/validated-changeset.es5.js?:2447:18)
                at Proxy.BufferedChangeset._validateKey (webpack://__ember_auto_import__/./node_modules/validated-changeset/dist/validated-changeset.es5.js?:2425:23)
                at eval (webpack://__ember_auto_import__/./node_modules/validated-changeset/dist/validated-changeset.es5.js?:2211:24)
        message: >
            Assertion Failed: You attempted to update `_errors` on `changeset:[object Object]`, but it had already been used previously in the same computation.  Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.

            `_errors` was first used:

            - While rendering:
              application
                forms
                  forms.form
                    form-workflow
                      form-workflow/form
                        form-for

Похоже, это внутренняя часть проверки ember-changeset-validations, выполняющая некоторый пересчет ошибок, но у меня еще не было полосы пропускания, чтобы в нее вникнуть. Хотя утверждение кажется точным и достоверным, его взрывы в моем тестовом пакете означают, что я заблокирован от обновления до 3.22, пока я не пойму, что происходит.

Попался. FWIW сообщение об ошибке действительно выглядит, по крайней мере, "полезным" для облегчения отладки.

@Yelinz - Я не думаю, что исходная проблема, о которой сообщалось (в твидле ), находится здесь в той же области (эти ошибки твидла, по крайней мере, начиная с сообщает @kpfefferle . Этот тидлл отражает вашу реальную ситуацию? С какой версии вы обновляетесь?

Как я уже сказал в своем предыдущем комментарии, это с 3.21 по 3.22, и ситуация аналогична @kpfefferle, только с другим аддоном. Я сделал ход, чтобы вызвать эту ошибку. Фактический код, который вызывает это, - это тот, который я опубликовал ранее.

2020-10-12T09:38:40.7310067Z         actual: >
2020-10-12T09:38:40.7310575Z             [object Object]
2020-10-12T09:38:40.7311080Z         stack: >
2020-10-12T09:38:40.7314024Z             Error: Assertion Failed: You attempted to update `__instance` on `<ember-caluma<strong i="7">@component</strong>:x-toggle-switch::ember726>`, but it had already been used previously in the same computation.  Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.
2020-10-12T09:38:40.7315638Z             
2020-10-12T09:38:40.7316183Z             `__instance` was first used:
2020-10-12T09:38:40.7316698Z             
2020-10-12T09:38:40.7317709Z             - While rendering:
2020-10-12T09:38:40.7318285Z               application
2020-10-12T09:38:40.7318787Z                 demo
2020-10-12T09:38:40.7319293Z                   application
2020-10-12T09:38:40.7319772Z             
2020-10-12T09:38:40.7320295Z             Stack trace for the update:
2020-10-12T09:38:40.7321118Z                 at dirtyTagFor (http://localhost:7357/assets/vendor.js:74216:9)
2020-10-12T09:38:40.7322185Z                 at markObjectAsDirty (http://localhost:7357/assets/vendor.js:31365:32)
2020-10-12T09:38:40.7323337Z                 at notifyPropertyChange (http://localhost:7357/assets/vendor.js:31403:5)
2020-10-12T09:38:40.7324352Z                 at _set2 (http://localhost:7357/assets/vendor.js:32379:9)
2020-10-12T09:38:40.7325263Z                 at Class.set (http://localhost:7357/assets/vendor.js:45923:29)
2020-10-12T09:38:40.7326501Z                 at Class.__teardownRecognizers (http://localhost:7357/assets/vendor.js:165238:14)
2020-10-12T09:38:40.7327580Z                 at sendEvent (http://localhost:7357/assets/vendor.js:30998:14)

Трассировка стека также более или менее похожа на его

Я сделал поворот, чтобы вызвать эту ошибку

Да, но существует множество сценариев, в которых эта ошибка должна быть выброшена (и возникла с тех пор, как было введено отслеживание). Нам нужно выяснить, какой _новый_ сценарий сейчас отслеживается, что ранее не отслеживалось. Для этого мне нужно понять схему использования.

Как только мы выясним, каков был шаблон использования, мы можем выяснить, можем ли мы изменить вещи, чтобы выдать устаревание вместо утверждения, но на данный момент у нас еще нет воспроизведения, которое представляет проблемы реального мира, с которыми вы все сталкиваетесь. поэтому я не могу точно сказать, можем ли мы преобразовать утверждение в устаревшее ...

Для всех, кто приходит сюда, я хотел бы видеть здесь воспроизведение (в идеале в виде сбоев теста на каком-то репо; будь то надстройка или просто демонстрационное приложение, созданное для этой цели), которое передается 3.21 и не работает на 3.22.

Это наш прохождение теста на ember 3.21.
https://github.com/projectcaluma/ember-caluma/pull/1065/checks?check_run_id=1241360614

Между тем тот же код не работает на 3.22
https://github.com/projectcaluma/ember-caluma/pull/1065/checks?check_run_id=1241408429

Проблема связана с длинным списком зависимостей, который заканчивается тлеющими жестами, и фрагментом кода, который я опубликовал ранее.

Спасибо за вашу помощь, ребята (и за терпение, пока я пытался понять, что происходит)!

Я буду работать над тем, чтобы в ближайшее время выпустить это в выпусках исправлений.

@rwjblue Спасибо вам и @pzuraq за _слежение_ за проблемой!

: wave: @rwjblue , вы все еще надеетесь выпустить патч 3.22.1 с этим исправлением? Я очень хочу обновить наше приложение до версии 3.22, дайте мне знать, если я могу чем-нибудь помочь.

Мы сталкивались с этим в ряде наших приложений из-за шаблона, установленного вокруг ember-changeset-validations . Вот пример используемого нами шаблона:

import Component from '@glimmer/component';
import Changeset from 'ember-changeset';
import lookupValidator from 'ember-changeset-validations';
import OrderValidations from '../validations/order';

export default class OrderFormComponent extends Component {
  constructor() {
    super(...arguments);

    let model = this.args.model;
    this.changeset = new Changeset(
      model,
      lookupValidator(OrderValidations),
      OrderValidations
    );
    this.changeset.validate();
  }
}

this.changeset.validate() вызывает ошибку утверждения в 3.22.0.

Я только что запустил выпуск v3.22.1 (https://github.com/emberjs/ember.js/releases/tag/v3.22.1), который должен быть опубликован в NPM в ближайшее время (после завершения CI).

Было ли это исправление действительно включено в выпуск v3.22.1, или, возможно, связанный PR не полностью устранил эту проблему? Я вижу https://github.com/emberjs/ember.js/pull/19193 в примечаниях к выпуску, но мой проект по-прежнему показывает те же ошибки тестирования, что и раньше 🤔

Подтверждено, также все еще вижу это в 3.22.1

Открытие для повторного расследования. Хотя упрощенная / минимальная демонстрация (проходит на 3.20 и терпит неудачу на 3.22) была бы действительно полезной.

Вот простой пример, который вызывает ошибку в 3.22.1 , но работает в 3.21 :

export default class ExampleComponent extends Component {
  <strong i="9">@tracked</strong> count = 0;

  constructor() {
    super(...arguments);

    this.count++; // this fails in 3.22.1
  }
}

3.21 :

Screenshot 2020-11-16 at 10 34 57

3.22.1 :

Screenshot 2020-11-16 at 10 34 30

Что-то не так с чтением и обновлением отслеживаемого свойства в конструкторе? Моя ментальная модель состоит в том, что это должно быть нормально, поскольку свойство является локальным для компонента, а мы еще ничего не отрендерили в DOM.

В приведенном выше примере также возникает утверждение относительно недавно помеченного 3.23.

@GavinJoyce - это пример, который вы предоставили с компонентами Glimmer? Мы намеревались исправить эту ошибку только в классических компонентах по причинам обратной совместимости, в компонентах Glimmer и в целом, двигаясь вперед, мы _до_ ожидаем, что подобные мутации не будут выполнены во время рендеринга. В общем, невозможно безопасно прочитать отслеживаемое состояние и затем записать в отслеживаемое состояние во время одного отслеживаемого вычисления.

Мы намеревались охватить все эти типы мутаций, поскольку утверждение было изначально усилено в 3.15, но конструкторы были пропущены из-за того, что внутренняя виртуальная машина не использовала автоматическое отслеживание.

Мы можем обернуть это с помощью помощника deprecateMutationsInAutotrackingFrame чтобы он на время выдавал устаревание вместо утверждения, чтобы предотвратить регресс приложений.

Мы можем обернуть это с помощью помощника deprecateMutationsInAutotrackingFrame чтобы он на время выдавал устаревание вместо утверждения, чтобы предотвратить регресс приложений.

Да, в этом есть смысл. На данный момент это разблокирует людей, но нам все еще нужны приложения / надстройки / и т. Д., Чтобы исправить основную проблему (мы просто не можем поддерживать «чтение, затем запись» в контексте отслеживания).

это пример, который вы предоставили с компонентами Glimmer?

Да, это компонент Glimmer.

Вот пример реальной проблемы, которая в настоящее время не позволяет нам обновиться: https://github.com/GavinJoyce/backdrifts/pull/5

Мутация данных модели (в данном случае вызов addFragment ) в конструкторе, безусловно, является анти-шаблоном, нам, скорее всего, следует сделать такую ​​мутацию модели, когда мы создаем модель в маршруте или на этапе действий. . Выдача сообщения об устаревании вместо утверждения даст приложениям, которые сталкиваются с подобными проблемами, некоторое время для выполнения этого рефакторинга.

Выдача сообщения об устаревании вместо утверждения даст приложениям, которые сталкиваются с подобными проблемами, некоторое время для выполнения этого рефакторинга.

Абсолютно согласен! Я собираюсь поработать сегодня утром.

Спасибо, LMK, если я могу чем-нибудь помочь

Это потребует некоторых изменений в glimmer-vm, которые я отправил в https://github.com/glimmerjs/glimmer-vm/pull/1205 , но интеграция Ember (чтобы сделать ее устаревшей) находится на https: // github. com / emberjs / ember.js / pull / 19282.

Только что внесены необходимые изменения в Glimmer, и я постараюсь выпустить релизы завтра.

Это было немного сложнее, чем я первоначально думал, поскольку мы должны гарантировать, что все типы объектов имеют поведение устаревания (по сравнению с утверждением). Я _think_ https://github.com/emberjs/ember.js/pull/19282 , наконец, готов к рассмотрению.

Следующие шаги здесь - это выполнить резервное копирование и протестировать изменения из glimmer-vm в нескольких разных версиях (где у каждой из них есть внутренние критические изменения):

Я еще не уверен на 100%, но вполне вероятно, что я выпущу это в версии 3.23.1+ (поскольку версия 3.22 больше не является текущим выпуском). Есть ли у кого-нибудь особая потребность в этом в версии 3.22 и не может ли вместо этого обновиться до версии 3.23?

Я более чем счастлив обновиться до 3.23.

Может быть, мне нужно еще кофе, но я робко признаю, что не совсем понимаю закономерность, которой мы должны избегать. Я понимаю пример, в котором вы устанавливаете значение в получателе, но я не совсем уверен, почему пример Гэвина плох (даже если он немного надуманный). Сможет ли кто-нибудь рассказать мне об этом?

Я не совсем уверен, есть ли еще что-то, что нужно сделать для обновления нашего приложения до версии 3.22 или 3.23. У нас есть сотни неудачных тестов на 3.22, подавляющее большинство из них, похоже, являются утверждениями с возвратом, которые, я надеюсь, будут исправлены вашими изменениями. Надеюсь, мы сможем сразу перейти с 3.21 на 3.23.1.

Если это не такая уж большая нагрузка, может быть, неплохо было бы выпустить и 3.22.2? Это может избавить людей, которые обновляют одну версию за раз, от головной боли в будущем.

К вашему сведению, я вижу это при запуске бета-теста ember в движке:

Screen Shot 2020-11-20 at 11 29 18 AM

Код нарушения:

<LinkToExternal @route="your-coach">{{@coachUser.firstName}}</LinkToExternal>

@jherdman убедитесь, что вы используете последний код движков ember, link-to-external был недавно обновлен, чтобы избежать этого утверждения (в https://github.com/ember-engines/ember-engines/pull/735).

К сожалению, я действительно использую двигатели v0.8.8. Я не хочу откладывать этот вопрос под откос, можно мне открыть там вопрос?

К сожалению, я действительно использую двигатели v0.8.8. Я не хочу откладывать этот вопрос под откос, можно мне открыть там вопрос?

Да, пожалуйста!

Может быть, мне нужно еще кофе, но я робко признаю, что не совсем понимаю закономерность, которой мы должны избегать. Я понимаю пример, в котором вы устанавливаете значение в получателе, но я не совсем уверен, почему пример Гэвина плох (даже если он немного надуманный). Сможет ли кто-нибудь рассказать мне об этом?

Концептуальная проблема здесь заключается в том, что при изменении отслеживаемого значения, которое уже было прочитано / использовано в текущем «кадре отслеживания», мы не можем гарантировать, что окончательное отображаемое значение является действительным. Например, представьте себе такую ​​установку:

  • что-то в маршруте вашего приложения обращается к {{this.someService.randomTrackedProperty}}
  • затем позже где-нибудь в шаблоне вложенного маршрута вы вызываете такой компонент, как <FooBar />
  • в конструкторе FooBar s он выполняет this.someService.randomTrackedProperty = "hello!"

Этот компонент, изменяющий предыдущее отслеживаемое значение чтения, означает, что любые другие ссылки на это значение теперь недействительны .

В приведенном выше примере Гэвинса он увеличивал счетчик, это обязательно означает, что вы читаете существующее значение, а затем обновляете его до нового значения. Я знаю, что это кажется безобидным, потому что значение является локальным для компонента, и в этом примере никакой другой код не имел доступа к «недействительной» версии (исходная версия до изменения), но на самом деле в конструкторе нет ничего особенного! . Отслеживаемая система - это целостная модель реактивности, и на самом деле нет ничего специализированного в инициализации компонента / помощника / модификатора (система работает так же хорошо, если вы вообще ничего не рендерируете).

Быстрое обновление здесь, 3.23.1 выпущена с исправлениями. Постараюсь завтра доделать 3.22.x (проблемы с подбором вишни).

Хорошо, 3.22.2 помечен и должен быть опубликован в NPM в ближайшее время.

Спасибо за отметку 3.22.2, думаю, нам будет полезно сначала перейти к ней.

К вашему сведению, похоже, он не будет опубликован в NPM через 10 часов: https://www.npmjs.com/package/ember-source/v/3.22.2

Просто исправлено, извините за это

Большое спасибо!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги