Consider the following code, and how it can be affected by the following transformations:
function foo () {
return {x: 5}
}
foo() === foo() // => falseThis function is statically compiled away by supporting transformers (which need to have esprima/acorn-level knowledge about scope and the like). Otherwise, it should either NOOP or error. The idea is that any expressions wrapped in loadTimeValue are yanked out into a module-level cache, and evaluated only once -- at the top level (so they don't see local function scope!), and a reference into that cache is inserted into the original callsite.
Thus, consider then the effect of using loadTimeValue in the base code:
function foo () {
return loadTimeValue({x: 5})
}This would be transformed into code like:
const __LOAD_TIME_VALUES__ = [
{x: 5}
]
function foo () {
return __LOAD_TIME_VALUES__[0]
}Which, would yield a different result in the expression we evaluated:
foo() === foo() // => trueNow consider the more familiar use of function inlining, assuming the ability to explicitly do so for existing functions:
function foo () {
"inline";
return {x: 5}
}Our original function would be extracted entirely, but our evaluated expression would transform into:
{x: 5} === {x: 5} // => falseInlining is fairly familiar, of course, and stuff like loadTimeValue is done manually all the time. But what about when we combine both?
function foo () {
"inline";
return loadTimeValue({x: 5})
}
foo() === foo() // => falseIdeally, we would first transform "inline"; declarations away, leaving us with only this code:
loadTimeValue({x: 5}) === loadTimeValue({x: 5})And the ltv would be replaced in the following pass, leaving us with:
const __LOAD_TIME_VALUES__ = [
{x: 5},
{x: 5}
]
__LOAD_TIME_VALUES__[0] === __LOAD_TIME_VALUES__[1] // falseThe examples here were more meant to show the mechanics involved, but in practice, both of these can turn out to be tremendously useful. Put together, they make it trivial to add general or inline caching to any similar values!
function timesCalled () {
"inline";
var counter = loadTimeValue({count: 0})
return ++counter.count
}
function caller() {
if (randomTruthy()) {
console.log('callsite #1 calls: ', timesCalled())
} else {
console.log('callsite #2 calls: ', timesCalled())
}
}
repeat(100, caller) // Prints different counts depending on how `randomTruthy` goes