mirror of
https://github.com/bigskysoftware/htmx.git
synced 2025-10-04 16:25:09 +00:00
config that disallows eval
in htmx implementation
addressed https://github.com/bigskysoftware/htmx/issues/305
This commit is contained in:
parent
3c7dde7e1f
commit
58f373d1e5
27
src/htmx.js
27
src/htmx.js
@ -42,6 +42,7 @@ return (function () {
|
|||||||
requestClass:'htmx-request',
|
requestClass:'htmx-request',
|
||||||
settlingClass:'htmx-settling',
|
settlingClass:'htmx-settling',
|
||||||
swappingClass:'htmx-swapping',
|
swappingClass:'htmx-swapping',
|
||||||
|
allowEval:true,
|
||||||
attributesToSettle:["class", "style", "width", "height"]
|
attributesToSettle:["class", "style", "width", "height"]
|
||||||
},
|
},
|
||||||
parseInterval:parseInterval,
|
parseInterval:parseInterval,
|
||||||
@ -248,7 +249,9 @@ return (function () {
|
|||||||
//==========================================================================================
|
//==========================================================================================
|
||||||
|
|
||||||
function internalEval(str){
|
function internalEval(str){
|
||||||
|
return maybeEval(getDocument().body, function () {
|
||||||
return eval(str);
|
return eval(str);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLoadHelper(callback) {
|
function onLoadHelper(callback) {
|
||||||
@ -735,7 +738,7 @@ return (function () {
|
|||||||
last !== ".";
|
last !== ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeGenerateConditional(tokens, paramName) {
|
function maybeGenerateConditional(elt, tokens, paramName) {
|
||||||
if (tokens[0] === '[') {
|
if (tokens[0] === '[') {
|
||||||
tokens.shift();
|
tokens.shift();
|
||||||
var bracketCount = 1;
|
var bracketCount = 1;
|
||||||
@ -752,7 +755,10 @@ return (function () {
|
|||||||
tokens.shift();
|
tokens.shift();
|
||||||
conditionalSource += ")})";
|
conditionalSource += ")})";
|
||||||
try {
|
try {
|
||||||
var conditionFunction = Function(conditionalSource)();
|
var conditionFunction = maybeEval(elt,function () {
|
||||||
|
return Function(conditionalSource)();
|
||||||
|
},
|
||||||
|
function(){return true})
|
||||||
conditionFunction.source = conditionalSource;
|
conditionFunction.source = conditionalSource;
|
||||||
return conditionFunction;
|
return conditionFunction;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -800,7 +806,7 @@ return (function () {
|
|||||||
triggerSpecs.push({trigger: 'sse', sseEvent: trigger.substr(4)});
|
triggerSpecs.push({trigger: 'sse', sseEvent: trigger.substr(4)});
|
||||||
} else {
|
} else {
|
||||||
var triggerSpec = {trigger: trigger};
|
var triggerSpec = {trigger: trigger};
|
||||||
var eventFilter = maybeGenerateConditional(tokens, "event");
|
var eventFilter = maybeGenerateConditional(elt, tokens, "event");
|
||||||
if (eventFilter) {
|
if (eventFilter) {
|
||||||
triggerSpec.eventFilter = eventFilter;
|
triggerSpec.eventFilter = eventFilter;
|
||||||
}
|
}
|
||||||
@ -1215,7 +1221,9 @@ return (function () {
|
|||||||
function evalScript(script) {
|
function evalScript(script) {
|
||||||
if (script.type === "text/javascript" || script.type === "") {
|
if (script.type === "text/javascript" || script.type === "") {
|
||||||
try {
|
try {
|
||||||
Function(script.innerText)();
|
maybeEval(script, function () {
|
||||||
|
Function(script.innerText)()
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError(e);
|
logError(e);
|
||||||
}
|
}
|
||||||
@ -1803,9 +1811,18 @@ return (function () {
|
|||||||
return getValuesForElement(parentElt(elt), attr, strToValues, expressionVars);
|
return getValuesForElement(parentElt(elt), attr, strToValues, expressionVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function maybeEval(elt, toEval, defaultVal) {
|
||||||
|
if (htmx.config.allowEval) {
|
||||||
|
return toEval();
|
||||||
|
} else {
|
||||||
|
triggerErrorEvent(elt, 'htmx:evalDisallowedError');
|
||||||
|
return defaultVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getHXVarsForElement(elt, expressionVars) {
|
function getHXVarsForElement(elt, expressionVars) {
|
||||||
return getValuesForElement(elt, "hx-vars", function(valueStr){
|
return getValuesForElement(elt, "hx-vars", function(valueStr){
|
||||||
return Function("return (" + valueStr + ")")()
|
return maybeEval(elt,function () {return Function("return (" + valueStr + ")")();}, {});
|
||||||
}, expressionVars);
|
}, expressionVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,5 +246,20 @@ describe("Core htmx API test", function(){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('eval can be suppressed', function () {
|
||||||
|
var calledEvent = false;
|
||||||
|
var handler = htmx.on("htmx:evalDisallowedError", function(){
|
||||||
|
calledEvent = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
htmx.config.allowEval = false;
|
||||||
|
should.equal(htmx._("tokenizeString"), undefined);
|
||||||
|
} finally {
|
||||||
|
htmx.config.allowEval = true;
|
||||||
|
htmx.off("htmx:evalDisallowedError", handler);
|
||||||
|
}
|
||||||
|
calledEvent.should.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
})
|
|
||||||
|
})
|
||||||
|
@ -34,7 +34,7 @@ describe("Core htmx tokenizer tests", function(){
|
|||||||
it('generates conditionals property', function()
|
it('generates conditionals property', function()
|
||||||
{
|
{
|
||||||
var tokens = tokenize("[code==4||(code==5&&foo==true)]");
|
var tokens = tokenize("[code==4||(code==5&&foo==true)]");
|
||||||
var conditional = htmx._("maybeGenerateConditional")(tokens);
|
var conditional = htmx._("maybeGenerateConditional")(null, tokens);
|
||||||
var func = eval(conditional);
|
var func = eval(conditional);
|
||||||
func({code: 5, foo: true}).should.equal(true);
|
func({code: 5, foo: true}).should.equal(true);
|
||||||
func({code: 5, foo: false}).should.equal(false);
|
func({code: 5, foo: false}).should.equal(false);
|
||||||
|
@ -95,6 +95,7 @@ Note that using a [meta tag](/docs/#config) is the preferred mechanism for setti
|
|||||||
* `requestClass:'htmx-request'` - string: the class to place on triggering elements when a request is in flight
|
* `requestClass:'htmx-request'` - string: the class to place on triggering elements when a request is in flight
|
||||||
* `settlingClass:'htmx-settling'` - string: the class to place on target elements when htmx is in the settling phase
|
* `settlingClass:'htmx-settling'` - string: the class to place on target elements when htmx is in the settling phase
|
||||||
* `swappingClass:'htmx-swapping'` - string: the class to place on target elements when htmx is in the swapping phase
|
* `swappingClass:'htmx-swapping'` - string: the class to place on target elements when htmx is in the swapping phase
|
||||||
|
* `allowEval:true` - boolean: allows the use of eval-like functionality in htmx, to enable `hx-vars`, trigger conditions & script tag evaluation. Can be set to `false` for CSP compatibility
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
|
|
||||||
|
@ -817,6 +817,7 @@ Htmx allows you to configure a few defaults:
|
|||||||
| `htmx.config.requestClass` | defaults to `htmx-request`
|
| `htmx.config.requestClass` | defaults to `htmx-request`
|
||||||
| `htmx.config.settlingClass` | defaults to `htmx-settling`
|
| `htmx.config.settlingClass` | defaults to `htmx-settling`
|
||||||
| `htmx.config.swappingClass` | defaults to `htmx-swapping`
|
| `htmx.config.swappingClass` | defaults to `htmx-swapping`
|
||||||
|
| `htmx.config.allowEval` | defaults to `true`
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user