标记的模板文字的 TemplateObject 数组是否被其领域弱引用?
Are TemplateObject arrays for tagged template literals weakly referenced by their realm?
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 Runtime Semantics: GetTemplateObject ( templateLiteral ) 部分描述了如何缓存此值:
- Let realm be the current Realm Record.
- Let templateRegistry be realm.[[TemplateMap]].
所以在上面的循环中使用 tag
应该是一样的,这将是一个很好的 属性 键。
在我看来 [[TemplateMap]] 必须弱引用模板对象数组,否则
for (let i = 0; i < 1e6; ++i) {
eval('(() => {})`' + i + '`');
}
会泄漏内存。
我在规范中没有看到任何内容,但是对于广泛使用的 JavaScript 引擎来说,标记字符串模板的 WeakMap 条目不在可重新输入范围内使用的情况最终会被收集吗?
我问是因为我已经根据这个假设实现了 something 但还没有想出如何测试它。
Is it okay to use that object as a key in a WeakMap to avoid having to redo work based on the array each time through the loop?
是的,这正是您想要做的,它是模板文字的重要功能之一。
It seems to me that the [[TemplateMap]] would have to weakly reference the template object array because otherwise
for (let i = 0; i < 1e6; ++i) {
eval('(() => {})`' + i + '`');
}
would leak memory.
它确实泄漏了,因为 [[TemplateMap]]
并不弱。 :(
这是对当前规范的公开讨论点。在撰写本文时,讨论的是是否应更改规范以使模板文字成为每个源文本位置,而不是让 [[TemplateMap]]
成为全局状态。例如在撰写本文时:
var id = v => v;
id`tpl` === id`tpl` // true
这有点奇怪。
创建两个单独的模板是否可以接受?如果是这样,那么至少有可能允许您的 eval
示例收集模板。
你可以在这里看到一些讨论,https://github.com/tc39/ecma262/issues/840,至少可以暂时解决这个问题。
编辑:
规范确实发生了变化,因此模板现在是按源位置而不是按领域的,因此具有相同内容和不同位置的两个模板将是两个不同的对象。这意味着如果引擎的源文件不再可用,引擎可能会垃圾收集模板文字对象。
It seems to me that the [[TemplateMap]] would have to weakly reference the template object array
我不知道这里的实际实现是什么,但规范确实将领域 [[TemplateMap]] 描述为永远不会被清空。在循环中评估许多不同的模板标签确实会严重泄漏内存,因此 don't do that.
Is it okay to use that object as a key in a WeakMap to avoid having to redo work?
是的,非常好。如果全局 [[TemplateMap]] 确实泄漏内存,这会加剧问题,但如果没有,那么通过使用 weak 映射就不会造成问题。
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 Runtime Semantics: GetTemplateObject ( templateLiteral ) 部分描述了如何缓存此值:
- Let realm be the current Realm Record.
- Let templateRegistry be realm.[[TemplateMap]].
所以在上面的循环中使用 tag
应该是一样的,这将是一个很好的 属性 键。
在我看来 [[TemplateMap]] 必须弱引用模板对象数组,否则
for (let i = 0; i < 1e6; ++i) {
eval('(() => {})`' + i + '`');
}
会泄漏内存。
我在规范中没有看到任何内容,但是对于广泛使用的 JavaScript 引擎来说,标记字符串模板的 WeakMap 条目不在可重新输入范围内使用的情况最终会被收集吗?
我问是因为我已经根据这个假设实现了 something 但还没有想出如何测试它。
Is it okay to use that object as a key in a WeakMap to avoid having to redo work based on the array each time through the loop?
是的,这正是您想要做的,它是模板文字的重要功能之一。
It seems to me that the [[TemplateMap]] would have to weakly reference the template object array because otherwise
for (let i = 0; i < 1e6; ++i) { eval('(() => {})`' + i + '`'); }
would leak memory.
它确实泄漏了,因为 [[TemplateMap]]
并不弱。 :(
这是对当前规范的公开讨论点。在撰写本文时,讨论的是是否应更改规范以使模板文字成为每个源文本位置,而不是让 [[TemplateMap]]
成为全局状态。例如在撰写本文时:
var id = v => v;
id`tpl` === id`tpl` // true
这有点奇怪。
创建两个单独的模板是否可以接受?如果是这样,那么至少有可能允许您的 eval
示例收集模板。
你可以在这里看到一些讨论,https://github.com/tc39/ecma262/issues/840,至少可以暂时解决这个问题。
编辑:
规范确实发生了变化,因此模板现在是按源位置而不是按领域的,因此具有相同内容和不同位置的两个模板将是两个不同的对象。这意味着如果引擎的源文件不再可用,引擎可能会垃圾收集模板文字对象。
It seems to me that the [[TemplateMap]] would have to weakly reference the template object array
我不知道这里的实际实现是什么,但规范确实将领域 [[TemplateMap]] 描述为永远不会被清空。在循环中评估许多不同的模板标签确实会严重泄漏内存,因此 don't do that.
Is it okay to use that object as a key in a WeakMap to avoid having to redo work?
是的,非常好。如果全局 [[TemplateMap]] 确实泄漏内存,这会加剧问题,但如果没有,那么通过使用 weak 映射就不会造成问题。