Resource Limits
New in version 1.4.0
For deployments where template authors are untrusted, you can set limits on some resources to avoid malicious templates from consuming too much memory or too many CPU cycles.
import { Environment } from "liquidscript";
const env = new Environment({
maxContextDepth: 30,
localNamespaceLimit: 3000,
loopIterationLimit: 1000,
outputStreamLimit: 15000,
});
const template = env.fromString(`
{% for x in (1..1000000) %}
{% for y in (1..1000000) %}
{{ x }},{{ y }}
{% endfor %}
{% endfor %}
`);
template.renderSync();
// LoopIterationLimitError: loop iteration limit reached (<string>:2)
Context Depth Limit
The maximum number of times a render context can be copied or extended before a ContextDepthError
is thrown. This helps us guard against recursive use of the include
or render
tags.
The maxContextDepth
option defaults to 30
.
import { Environment, ObjectLoader } from "liquidscript";
const templates = {
foo: "{% render 'bar' %}",
bar: "{% render 'foo' %}",
};
const env = new Environment({
loader: new ObjectLoader(templates),
maxContextDepth: 30,
});
const template = env.fromString("{% render 'foo' %}");
template.renderSync();
// ContextDepthError: maximum context depth reached, possible recursive render (bar:1)
Local Namespace Limit
The maximum "size" of a render context local namespace. Rather than the number of bytes in memory a local namespace occupies, "size" is a non-specific indication of how much a template uses the local namespace when it is rendered, typically using the assign
and capture
tags.
If the localNamespaceLimit
option is undefined
or less than 0
, there is no limit. Otherwise a LocalNamespaceLimitError
is thrown when the namespace's size exceeds the limit.
import { Environment } from "liquidscript";
const env = new Environment({
localNamespaceLimit: 50, // Very low, for demonstration purposes.
});
const template = env.fromString(
'{% assign x = "Nunc est nulla, pellentesque ac dui id erat curae." %}'
);
template.renderSync();
// LocalNamespaceLimitError: local namespace limit reached (<string>:1)
Loop Iteration Limit
The maximum number of loop iteration allowed before a LoopIterationLimitError
is thrown.
If the loopIterationLimit
option is undefined
or less than 0
, there is no soft limit.
import { Environment } from "liquidscript";
const env = new Environment({
loopIterationLimit: 999,
});
const template = env.fromString(`
{% for x in (1..100) %}
{% for y in (1..100) %}
{{ x }},{{ y }}
{% endfor %}
{% endfor %}
`);
template.renderSync();
// LoopIterationLimitError: loop iteration limit reached (<string>:2)
Other built in tags that contribute to the loop iteration counter are render
, include
(when using their {% render 'thing' for some.thing %}
syntax) and tablerow
. If a partial template is rendered within a for
loop, the loop counter is carried over to the render context of the partial template.
Output Stream Limit
The maximum number of bytes that can be written to a template's output stream, per render, before an OutputStreamLimitError
is thrown.
If the outputStreamLimit
option is undefined
or less than 0
, there is no soft limit.
import { Environment } from "liquidscript";
const env = new Environment({
outputStreamLimit: 20, // Very low, for demonstration purposes.
});
const template = env.fromString(`
{% if false %}
this is never rendered, so will not contribute the the output byte counter
{% endif %}
Hello, {{ you }}!
`);
template.renderSync({ you: "World" });
// "\nHello, World!\n"
template.renderSync({ you: "something longer that exceeds our limit" });
// OutputStreamLimitError: output stream limit reached (<string>:5)