Неужели массивы TemplateObject для теговых литералов шаблонов слабо связаны с их областью?

while (c) {
  tag`str0 ${e} str1`
}

Среда выполнения JavaScript создает замороженный массив, например Object.freeze(['str0 ', ' str1']) но с дополнительным .raw имущество.

Можно ли использовать этот объект в качестве ключа в WeakMap чтобы избежать необходимости повторять работу на основе массива каждый раз через цикл?

const memoTable = new WeakMap
function tag(templateStrings, ...values) {
  let cached = memoTable.get(templateStrings)
  if (!cached) {
    // Compute cached and put it in the table for next time.
  }
  // Do something with cached and values
}

Раздел 12.2.9.3 Семантика времени выполнения: GetTemplateObject (templateLiteral) описывает, как это значение кэшируется:

  1. Пусть realm будет текущей записью Realm.
  2. Пусть templateRegistry будет царством.[[TemplateMap]].

так должно быть то же самое от использования к использованию tag в цикле выше, который был бы хорошим свойством для ключа.

Мне кажется, что [[TemplateMap]] должен был бы слабо ссылаться на массив объекта шаблона, потому что в противном случае

for (let i = 0; i < 1e6; ++i) {
  eval('(() => {})`' + i + '`');
}

будет утечка памяти.

Я ничего не вижу в спецификации, но так ли это в случае широко используемых движков JavaScript, когда в итоге будут собраны записи WeakMap для шаблона теговой строки, не входящего в области видимости?

Я спрашиваю, потому что я реализовал что-то на основе этого предположения, но не выяснил, как это проверить.

2 ответа

Решение

Можно ли использовать этот объект в качестве ключа в WeakMap, чтобы избежать необходимости каждый раз повторять работу на основе массива в цикле?

Да, это именно то, что вы должны делать, и это одна из замечательных возможностей литералов шаблонов.

Мне кажется, что [[TemplateMap]] должен был бы слабо ссылаться на массив объекта шаблона, потому что в противном случае

for (let i = 0; i < 1e6; ++i) {
  eval('(() => {})`' + i + '`');
}

будет утечка памяти.

Это действительно утечка, так как [[TemplateMap]] не слабый:(

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

var id = v => v;
id`tpl` === id`tpl` // true

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

Вы можете увидеть некоторые обсуждения здесь, https://github.com/tc39/ecma262/issues/840, где хотя бы ориентировочно это можно исправить.

Мне кажется, что [[TemplateMap]] должен был бы слабо ссылаться на массив объекта шаблона

Я не знаю, что на самом деле здесь делают реализации, но спецификация действительно описывает сферы [[TemplateMap]] как никогда не опустошаемые. Оценка множества различных шаблонных тегов в цикле действительно сильно утечет память, так что не делайте этого.

Можно ли использовать этот объект в качестве ключа в WeakMap, чтобы избежать необходимости повторной работы?

Да, это прекрасно. Если глобальный [[TemplateMap]] действительно пропускает память, это усугубит проблему, но когда этого не произойдет, использование слабой карты не вызовет проблемы.

Другие вопросы по тегам