Начиная с версии 2.3.1 пользовательские разделители больше не работают для Mustache.parse()
. См. следующие примеры:
Скорее всего, это связано с #663 и его исправлением. Обратите внимание, что я могу восстановить это, используя вместо этого более новый Mustache.tags = [...]
: https://codepen.io/mbrodala/pen/QBJoOx
Не могли бы вы взглянуть на это?
Большое спасибо за отчет @mbroda , эти коды очень ценны!
@mbroda Спасибо за кодовые ручки.
Интересно, было ли здесь недоразумение.
describe('when parsing a template with tags specified followed by the same template with different tags specified', function() {
it('returns different tokens for the latter parse', function() {
var template = "(foo)[bar]";
var parsedWithParens = Mustache.parse(template, ['(', ')']);
var parsedWithBrackets = Mustache.parse(template, ['[', ']']);
assert.notDeepEqual(parsedWithBrackets, parsedWithParens);
});
});
Функция parse
выполняла кеширование, используя только template
в качестве ключа кэша, так что в следующий раз, когда parse
будет использоваться для разбора этого шаблона, она вернет точно такие же токены, даже если указанные tags
отличаются.
tags
— необязательный параметр, и когда он опущен, он возвращается к mustache.tags
, что по умолчанию равно ['{{', '}}']
. Откат mustache.tags
используется как часть ключа кэша.
Я думаю, что знаю, что происходит в отношении исправления ошибок и ожиданий, и я попытаюсь пройти через это, и я буду использовать codepen в качестве примера.
Mustache.parse(template, ['[[', ']]']);
В версии 2.3.0 это указывает Mustache анализировать template
, используя ['[[', ']]']
в качестве тегов. Mustache делает это и возвращает правильный результат, но кэширует вызов, используя только template
. См. строки 447-450 [email protected]
:
if (tokens == null)
tokens = cache[template] = parseTemplate(template, tags);
Следующий вызов в codepen:
var output = Mustache.render(
template,
...
render
не принимает параметр tags
, поэтому не передает его в parse
, поэтому при вызове render
parse
использует mustache.tags
в качестве его тегов. Таким образом, когда выполняется этот вызов render
, он фактически сообщает parse
: «Пожалуйста, проанализируйте template
и неявно используйте ['{{', '}}']
как tags
». parse
на самом деле делает неправильную вещь и выполняет поиск в кеше, полностью игнорируя как tags
, так и mustache.tags
. Бывает, что возвращается результат анализа шаблона с [['[', ']']]
, но только потому, что первый вызов parse
во всей программе для этого template
был сделан с ['[[', ']']]
как tags
.
Mustache.parse(template, ['[[', ']]']);
Результат синтаксического анализа кэшируется с использованием template
и tags
, что равно ['[[', ']]']
в качестве cacheKey.
Следующий звонок:
var output = Mustache.render(
template,
...
render
вызывает parse
, передавая template
, но пропуская tags
. Таким образом, для $ parse
значение tags
возвращается к mustache.tags
, которое остается значением по умолчанию ['{{', '}}']
. parse
выполняет поиск в кеше по ключу кеша template
и ['{{', '}}']
и вызывает промах кеша, как и ожидалось, поскольку parse
еще не был вызван с этой комбинацией template
и тегов. Поэтому он анализирует template
с помощью ['{{', '}}']
.
Я считаю, что v2.3.1 показывает правильное поведение. Если бы мы немного изменили codepen в https://codepen.io/mbrodala/pen/QBJoOx и запустили его против версии 2.3.0:
var template = "[[item.title]] [[item.value]]";
Mustache.parse(template, ['[[', ']]']);
var output = Mustache.render(
template,
{
item: {
title: "TEST",
value: 1
}
}
);
alert(output);
Вывод [[item.title]] [[item.value]]
не ожидается.
Я вижу, как поведение в https://codepen.io/mbroda/pen/NBEJjX может быть удивительным, поскольку вызовы Mustache.parse
и Mustache.render
находятся рядом друг с другом, и один может не даже понять, что Mustache.parse
даже принимает аргумент tags
. (Почему Mustache.parse
даже принимает аргумент tags
? Он никогда нигде не используется в mustache.js
-- parse
просто по умолчанию имеет внутреннее значение mustache.tags
. ..)
Если изменение в поведении действительно бросает вызов ожиданиям выпуска исправления ошибок, то я не совсем уверен, что делать. Одна из возможностей состоит в том, чтобы выпустить еще одну версию с исправлением ошибок с откатом #664, который, по сути, удаляет все поведение кэширования (учитывая, что в #643 все поиски в кэше будут пропущены). Затем мы могли бы вернуть #664 в следующую основную версию. Другая возможность — удалить все кэширование в выпуске с исправлением ошибок (в отличие от выпуска mustache.js
с нефункциональным кэшированием), а затем вернуть все кэширование в следующей основной версии. Первый вариант, вероятно, имеет меньший риск (наименьшее количество изменений кода), но второй вариант, вероятно, более «правильный». мысли @phillipj ?
Большое спасибо за подробное исследование, которое полностью понятно из моего POV.
Я бы вообще не возражал против этого изменения, но учитывая, что невозможно передать tags
в Mustache.render()
, чтобы гарантировать попадание в кеш, и что Mustache.parse()
объявляется для кэширования template
(здесь не упоминается tags
) Интересно, действительно ли это следует отменить.
Если мы предположим, что кто-то вызывает Mustache.parse
с пользовательским набором tags
, мы также можем предположить, что template
использует эти разделители (кстати, «теги» и «разделители» должны быть тоже разобрался). После этого мы можем предположить, что вызов Mustache.render
должен работать, независимо от того, как и если данный template
уже кэширован и как он был скомпилирован, если это так. Сейчас это не гарантируется в случае использования пользовательских tags
.
@mbrodala Да, это имеет смысл, хотя Mustache.parse(template, ['[[', ']]']);
, за которым следует Mustache.parse(template, ['((', '))']);
, дающее точно такой же результат, все равно было бы неожиданным.
Вот соломенное решение/компромисс («соломенное чучело», потому что мне это не нравится, но стоит провести мозговой штурм). Мы могли бы иметь кэш $# parse
2$#$ как для одного template
, так и для template
с тегами. Когда parse
вызывается с указанным tags
, выполняется поиск по template
и tags
. Когда мы вызываем render
, который вызывает parse
без tags
, мы выполняем поиск только по template
. Мысли?
Звучит не так, и в основном это так, но мы исправим эту проблему, сохранив при этом исправление. ОК от моего POV.
@mbroda - это основная проблема, из-за которой вы не можете передать tags
в render
? Мы также можем просто добавить параметр tags
к render
.
@petrkoutnysw Это примерно та же проблема, с которой вы столкнулись?
Это как минимум несоответствие между parse()
и render()
. Мы бы даже не использовали parse()
, если бы действительно могли передавать пользовательские теги в render()
. И теперь с правильным кэшированием это становится более очевидным.
+1 за добавление параметра tags в render(), чтобы устранить большую путаницу — мы также получили немного от этого изменения, и ссылка на ч/б анализ и рендеринг всегда казалась немного более волшебной, чем необходимо.
Итак, как насчет того, чтобы отключить кэширование в выпуске с исправлением ошибок, чтобы исправить насущную проблему и обеспечить соблюдение семантического управления версиями, а также повторно ввести его и tags
в методе render
в следующем основном выпуске? (Опять же, я не большой поклонник предложенного мной соломенного решения.)
Большое спасибо за подробное руководство @raymond-lam!
Я склоняюсь к предлагаемому выпуску исправления ошибок, в основном из-за некоторых проблем и проектов, где это изменение поведения является неожиданным и, следовательно, может вызвать хаос в проектах в дикой природе.
Повторно представляя поведение кэширования снова в запланированном следующем основном выпуске, мы можем включить инструкции по миграции в примечания к выпуску.
@phillipj Я отправил запрос на включение # 670, который откатывает # 643 и # 664. Вместо того, чтобы полностью отключать кэширование, ради снижения риска, просто вернуться к поведению версии 2.3.0 (в выпуске с исправлением ошибок) кажется наиболее безопасным для тех, кто зависит от Mustache v2.xx. Я отправлю еще один запрос на включение для повторного введения в основной выпуск.
@phillipj #671 повторно вводит исправления кэширования, чтобы дождаться основного выпуска.
Создана проблема № 672 для решения вопроса о добавлении tags
в `render.
Большое спасибо за изучение и исправление этого, вы молодцы. 👍
Снимаю шляпу перед @raymond-lam за это! Спасибо вам, нам очень важно знать, когда в дикой природе происходят неожиданные изменения.
Опубликована версия 2.3.2 🚀