Skip to content

Commit

Permalink
Merge pull request knockout#814 from SteveSanderson/814-prevent-inval…
Browse files Browse the repository at this point in the history
…id-binding

Prevent invalid binding in re-written templates
  • Loading branch information
SteveSanderson committed Mar 19, 2013
2 parents bb46e03 + 1dfd516 commit a703974
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 21 deletions.
18 changes: 10 additions & 8 deletions src/templating/templateRewriting.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

ko.templateRewriting = (function () {
var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
var memoizeDataBindingAttributeSyntaxRegex = /(<([a-z]+\d*)(?:\s+(?!data-bind=)[a-z0-9\-]+(?:=(?:\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\3/gi;
var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;

function validateDataBindValuesForRewriting(keyValueArray) {
Expand All @@ -21,7 +21,7 @@ ko.templateRewriting = (function () {
}
}

function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, nodeName, templateEngine) {
var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
validateDataBindValuesForRewriting(dataBindKeyValueArray);
var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
Expand All @@ -30,7 +30,7 @@ ko.templateRewriting = (function () {
// anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
// extra indirection.
var applyBindingsToNextSiblingScript =
"ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
"ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()},'" + nodeName.toLowerCase() + "')";
return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
}

Expand All @@ -44,16 +44,18 @@ ko.templateRewriting = (function () {

memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[4], /* tagToRetain: */ arguments[1], /* nodeName: */ arguments[2], templateEngine);
}).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", /* nodeName: */ "#comment", templateEngine);
});
},

applyMemoizedBindingsToNextSibling: function (bindings) {
applyMemoizedBindingsToNextSibling: function (bindings, nodeName) {
return ko.memoization.memoize(function (domNode, bindingContext) {
if (domNode.nextSibling)
ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
var nodeToBind = domNode.nextSibling;
if (nodeToBind && nodeToBind.nodeName.toLowerCase() === nodeName) {
ko.applyBindingsToNode(nodeToBind, bindings, bindingContext);
}
});
}
}
Expand Down
22 changes: 9 additions & 13 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,21 +329,17 @@ ko.utils = (function () {
if ((value === null) || (value === undefined))
value = "";

if (element.nodeType === 3) {
element.data = value;
// We need there to be exactly one child: a text node.
// If there are no children, more than one, or if it's not a text node,
// we'll clear everything and create a single text node.
var innerTextNode = ko.virtualElements.firstChild(element);
if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
} else {
// We need there to be exactly one child: a text node.
// If there are no children, more than one, or if it's not a text node,
// we'll clear everything and create a single text node.
var innerTextNode = ko.virtualElements.firstChild(element);
if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
} else {
innerTextNode.data = value;
}

ko.utils.forceRefresh(element);
innerTextNode.data = value;
}

ko.utils.forceRefresh(element);
},

setElementName: function(element, name) {
Expand Down

0 comments on commit a703974

Please sign in to comment.