Skip to content

Commit

Permalink
Fix hx-on/hx-on:* to suppress evaluation if allowEval is false (#1682)
Browse files Browse the repository at this point in the history
* Added more tests for allowEval=false

* Wrap hx-on event handlers in maybeEval

* Create and cache hx-on function on first event trigger.
  • Loading branch information
jollytoad committed Aug 24, 2023
1 parent 212c9fb commit 94623d1
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/htmx.js
Expand Up @@ -1929,18 +1929,22 @@ return (function () {
function addHxOnEventHandler(elt, eventName, code) {
var nodeData = getInternalData(elt);
nodeData.onHandlers = [];
var func = new Function("event", code + "; return;");
var func;
var listener = function (e) {
return func.call(elt, e);
return maybeEval(elt, function() {
if (!func) {
func = new Function("event", code);
}
func.call(elt, e);
});
};
elt.addEventListener(eventName, listener);
nodeData.onHandlers.push({event:eventName, listener:listener});
return {nodeData:nodeData, code:code, func:func, listener:listener};
}

function processHxOn(elt) {
var hxOnValue = getAttributeValue(elt, 'hx-on');
if (hxOnValue && htmx.config.allowEval) {
if (hxOnValue) {
var handlers = {}
var lines = hxOnValue.split("\n");
var currentEvent = null;
Expand Down
17 changes: 17 additions & 0 deletions test/attributes/hx-on-wildcard.js
Expand Up @@ -130,4 +130,21 @@ describe("hx-on:* attribute", function() {
delete window.tempCount;
});

it("is not evaluated when allowEval is false", function () {
var calledEvent = false;
var handler = htmx.on("htmx:evalDisallowedError", function(){
calledEvent = true;
});
htmx.config.allowEval = false;
try {
var btn = make("<button hx-on:click='window.foo = true'>Foo</button>");
btn.click();
should.not.exist(window.foo);
} finally {
htmx.config.allowEval = true;
htmx.off("htmx:evalDisallowedError", handler);
delete window.foo;
}
calledEvent.should.equal(true);
});
});
17 changes: 17 additions & 0 deletions test/attributes/hx-on.js
Expand Up @@ -119,4 +119,21 @@ describe("hx-on attribute", function() {
delete window.tempCount;
});

it("is not evaluated when allowEval is false", function () {
var calledEvent = false;
var handler = htmx.on("htmx:evalDisallowedError", function(){
calledEvent = true;
});
htmx.config.allowEval = false;
try {
var btn = make("<button hx-on='click: window.foo = true'>Foo</button>");
btn.click();
should.not.exist(window.foo);
} finally {
htmx.config.allowEval = true;
htmx.off("htmx:evalDisallowedError", handler);
delete window.foo;
}
calledEvent.should.equal(true);
});
});
45 changes: 45 additions & 0 deletions test/attributes/hx-vals.js
Expand Up @@ -252,4 +252,49 @@ describe("hx-vals attribute", function() {
div.innerHTML.should.equal("Clicked!");
});

it('javascript: is not evaluated when allowEval is false', function () {
var calledEvent = false;
var handler = htmx.on("htmx:evalDisallowedError", function(){
calledEvent = true;
});
try {
htmx.config.allowEval = false;
this.server.respondWith("POST", "/vars", function (xhr) {
var params = getParameters(xhr);
should.not.exist(params['i1']);
xhr.respond(200, {}, "Clicked!")
});
var div = make('<div hx-post="/vars" hx-vals="javascript:i1:\'test\'"></div>')
div.click();
this.server.respond();
div.innerHTML.should.equal("Clicked!");
} finally {
htmx.config.allowEval = true;
htmx.off("htmx:evalDisallowedError", handler);
}
calledEvent.should.equal(true);
});

it('js: is not evaluated when allowEval is false', function () {
var calledEvent = false;
var handler = htmx.on("htmx:evalDisallowedError", function(){
calledEvent = true;
});
try {
htmx.config.allowEval = false;
this.server.respondWith("POST", "/vars", function (xhr) {
var params = getParameters(xhr);
should.not.exist(params['i1']);
xhr.respond(200, {}, "Clicked!")
});
var div = make('<div hx-post="/vars" hx-vals="js:i1:\'test\'"></div>')
div.click();
this.server.respond();
div.innerHTML.should.equal("Clicked!");
} finally {
htmx.config.allowEval = true;
htmx.off("htmx:evalDisallowedError", handler);
}
calledEvent.should.equal(true);
});
});
22 changes: 22 additions & 0 deletions test/attributes/hx-vars.js
Expand Up @@ -152,4 +152,26 @@ describe("hx-vars attribute", function() {
div.innerHTML.should.equal("Clicked!");
});

it('is not evaluated when allowEval is false', function () {
var calledEvent = false;
var handler = htmx.on("htmx:evalDisallowedError", function(){
calledEvent = true;
});
try {
htmx.config.allowEval = false;
this.server.respondWith("POST", "/vars", function (xhr) {
var params = getParameters(xhr);
should.not.exist(params['i1']);
xhr.respond(200, {}, "Clicked!")
});
var div = make('<div hx-post="/vars" hx-vals="javascript:i1:\'test\'"></div>')
div.click();
this.server.respond();
div.innerHTML.should.equal("Clicked!");
} finally {
htmx.config.allowEval = true;
htmx.off("htmx:evalDisallowedError", handler);
}
calledEvent.should.equal(true);
});
});

0 comments on commit 94623d1

Please sign in to comment.