You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by we...@apache.org on 2010/06/30 22:24:22 UTC
svn commit: r959421 - in
/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl:
_util/_Dom.js _util/_HtmlStripper.js _util/_Lang.js core/Impl.js
core/_Runtime.js xhrCore/_AjaxResponse.js
Author: werpu
Date: Wed Jun 30 20:24:21 2010
New Revision: 959421
URL: http://svn.apache.org/viewvc?rev=959421&view=rev
Log:
https://issues.apache.org/jira/browse/MYFACES-2761
Render All now also causes the evaluation of the head scripts, dropping of the ll parser in favor of browser based
parsing with a small html tag stripper as failsafe solution.
(significant reduction in final codesize)
Modified:
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js?rev=959421&r1=959420&r2=959421&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Dom.js Wed Jun 30 20:24:21 2010
@@ -64,22 +64,22 @@ myfaces._impl.core._Runtime.singletonExt
* (IE doesn't do this by itself)
* @param {|Node|} item
*/
- runScripts: function(item) {
+ runScripts: function(item, xmlData) {
var execScrpt = myfaces._impl._util._Lang.hitch(this, function(item) {
if (item.tagName && item.tagName.toLowerCase() == 'script') {
var src = item.getAttribute('src');
- if ( 'undefined' != typeof src
- && null != src
+ if ('undefined' != typeof src
+ && null != src
&& src.length > 0
- ) {
+ ) {
//we have to move this into an inner if because chrome otherwise chokes
//due to changing the and order instead of relying on left to right
if ((src.indexOf("ln=scripts") == -1 && src.indexOf("ln=javax.faces") == -1) || (src.indexOf("/jsf.js") == -1
- && src.indexOf("/jsf-uncompressed.js") == -1))
- myfaces._impl.core._Runtime.loadScriptEval(src, item.getAttribute('type'), false, "UTF-8");
+ && src.indexOf("/jsf-uncompressed.js") == -1))
+ myfaces._impl.core._Runtime.loadScriptEval(src, item.getAttribute('type'), false, "UTF-8");
} else {
// embedded script auto eval
- var test = item.text;
+ var test = (!xmlData) ? item.text :myfaces._impl._util._Lang.serializeChilds(item);
var go = true;
while (go) {
go = false;
@@ -236,7 +236,26 @@ myfaces._impl.core._Runtime.singletonExt
evalNodes = dummyPlaceHolder.childNodes[0].childNodes;
}
- parentNode = item.parentNode;
+ evalNodes = this.replaceElement(item, evalNodes);
+
+ //if this as well will fail in the future, we can let ie parse a proper xml
+ //extract the script elements and then create the script elements manually
+ //but for now we will not need it, and this solution is faster
+ //the downside of that solution would be that the fragment itself
+ //must resolve to a valid xml
+ return evalNodes;
+ },
+
+ /**
+ * replaces an element with another element or a set of elements
+ *
+ * @param item the item to be replaced
+ *
+ * @param evalNodes the elements
+ */
+ replaceElement: function (item, evalNodes) {
+ var _Lang = myfaces._impl._util._Lang;
+ var parentNode = item.parentNode;
if ('undefined' != typeof evalNodes.length) {
var oldNode = item;
@@ -259,12 +278,6 @@ myfaces._impl.core._Runtime.singletonExt
} else {
evalNodes = parentNode.replaceChild(evalNodes, item);
}
-
- //if this as well will fail in the future, we can let ie parse a proper xml
- //extract the script elements and then create the script elements manually
- //but for now we will not need it, and this solution is faster
- //the downside of that solution would be that the fragment itself
- //must resolve to a valid xml
return evalNodes;
},
@@ -499,7 +512,7 @@ myfaces._impl.core._Runtime.singletonExt
//but only for deep scan and normal parent nodes
else if (fragment.querySelectorAll && deepScan) {
try {
- var result = fragment.querySelectorAll("."+styleClass.replace(/\./g, "\\."));
+ var result = fragment.querySelectorAll("." + styleClass.replace(/\./g, "\\."));
if (fragment.nodeType == 1 && filter(fragment)) {
result = (result == null) ? [] : result;
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js?rev=959421&r1=959420&r2=959421&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_HtmlStripper.js Wed Jun 30 20:24:21 2010
@@ -16,38 +16,8 @@
/**
* <p>
- * A simple html parser class
- * that handles the stripping of the body
- * and head area properly
- * </p>
- * <p>
- * we assume that the ajax response encapsules
- * the html elements
- * so we only have to strip those really needed by the response
- * </p>
- * Due to this fact we can make several shortcuts...
- * First we only have to parse either for html or body for now
- * hence we can skip code and pre parsing to skip embedded tags as well
- *
- * <p>
- * secondly once we have found our section we can parse bottom up
- * which adds an additional speedup to our parsing process!
- * </p>
- * <p>
- * Note we do not solve the head and body stripping via regular expressions
- * because there are usecases where this does not work out
- * for instance comments with embedded head and body sections
- * or javascripts with head and body in strings..
- *
- * Also we do not rely on the response being xhtml due to
- * the fact that we might still have to cover jsp over html 4.0.1
- *
- * We tried to solve that that way in the first place but due to
- * the nature of things a minimal semantic understanding in the parsing
- * process is needed to strip everything out correctly which is not entirely
- * given via normal pattern matching, so we went the hard route
- * of implementing everything with a minimal parser
- * which tries to cover the semantics needed to strip out the correct content!
+ * Fallback routine if the browser embedded xml parser fails on the document
+ * This fallback is not failsafe but should give enough cover to handle all cases
* </p>
*/
@@ -56,18 +26,7 @@ myfaces._impl.core._Runtime.extendClass(
BEGIN_TAG: "html",
END_TAG: "lmth",
-
- /**
- * parses the token array
- * and handles the incoming tokens via an ll
- * parsing and backtracking of one char
- * the handling of the parsing is done via
- * recursive descension
- *
- * note in the subroutines the tokenPos must be at the last char of the operation
- * so that the
- */
- parse : function(theString, tagNameStart, tagNameEnd) {
+ parse : function(theString, tagNameStart) {
this.tokens = theString.split("");
this.tagAttributes = {};
@@ -81,545 +40,74 @@ myfaces._impl.core._Runtime.extendClass(
this._tokenForward = 1;
this.tagNameStart = (!tagNameStart) ? this.BEGIN_TAG : tagNameStart;
- this.tagNameEnd = (!tagNameEnd) ? this.tagNameStart.split("").reverse().join("") : tagNameEnd.split("").reverse().join("");
-
- this.handleInstructionBlock();
-
- if (this._contentStart >= 0 && this._contentEnd == -1) {
- this._tokenPos = this.tokens.length - 1;
- this._tokenForward = -1;
- //we now can skip the parsing for the rest of the block and have to roll out the parsing
- //from bottom up, this speeds up the entire process tremendously!
- this.handleEndBlock();
- }
-
- if (this._contentStart >= 0 && this._contentEnd == -1) {
- this._contentEnd = this.tokens.length - 1;
- } else if (this._contentStart == -1) {
- return "";
- }
- return this.tokens.slice(this._contentStart, this._contentEnd + 1).join("");
-
- },
-
- /**
- * fetches the content block which has been parsed
- */
- getContentBlock : function() {
- return this.tokens.slice(this._contentStart, this._contentEnd + 1).join("");
- },
-
- /**
- * fetches the content tag block including the tag code
- */
- getContentTagBlock : function() {
- return this.tokens.slice(this._tagStart, this._tagEnd + 1).join("");
- },
-
- /**
- * fetches the block before the tag begin
- */
- getPreTagBlock : function() {
- return this.tokens.slice(0, this._tagStart).join("");
- },
-
- /**
- * fetches the block after the tag end
- */
- getPostTagBlock : function() {
- return this.tokens.slice(this._tagEnd, this.tokens.length).join("");
- },
-
- /**
- * normal characters are skipped
- * a < clearly is an indicator for
- * a ... normal chars should not occur here, but
- * in the long run for deeper parsing they might happen!
- */
- handleInstructionBlock : function() {
- var len = this.tokens.length;
- for (; this._contentStart < 0 && this._tokenPos < len && this._tokenPos >= 0; this._tokenPos += this._tokenForward) {
- this._skipBlank();
- var token = this._getCurrentToken();
- if (token == "<") {
- this.handleDocument();
- }
- }
- },
-
- /**
- * it is either a datablock or a content tag from which we can start parsing
- */
- handleDocument : function() {
-
- this._tagStart = this.tokenPos;
- this._skipBlank(1);
-
- if (this._tokenPos >= this.tokens.length) {
- throw new Error("Document end reached prematurely");
- }
- var token = this._getCurrentToken();
- switch (token) {
- case "!":
- this.handleDataBlock();
- break;
-
- default: this.handleContentTag();
- }
- },
-
- /**
- * we can skip definitions or comments!
- *
- * a definition or comment section is like following:
- * <! ... > with no </ at the end
- *
- * with comments followed by --
- * and definitions followed by nothing else
- *
- */
- handleDataBlock : function() {
- this._skipBlank(1);
-
- if (this._tokenPos >= this.tokens.length || this._tokenPos < 0) {
- return;
- }
- var token = this.tokens[this._tokenPos];
- switch (token) {
- case "-":
- this.handleComment();
- break;
-
- default:
- this._getCurrentToken();
- this.handleDocDefinition();
- break;
- }
-
- },
-
- /**
- * doc definition ==
- * <! [^>] >
- */
- handleDocDefinition : function() {
- this._skipBlank();
-
- if (this._tokenPos >= this.tokens.length || this._tokenPos < 0) {
- throw new Error("Document end reached prematurely");
- }
- var len = this.tokens.length;
- while (this._tokenPos < len && this._tokenPos >= 0) {
- //var token = this._getCurrentToken();
- //inlining for speed reasons we also could use getCurrentToken
- var token = this.tokens[this._tokenPos];
-
- //inlining end
- if (token == ">") {
- return;
- }
- this._tokenPos += this._tokenForward;
- }
-
- },
-
- /**
- * General tag andling section
- * we define identified and unidentified content
- * and script which is a subpart of idenitifed
- *
- * for now we do not handle the special conditions within pre and code
- * segments since we have a specialized usage of this stripper
- * on head and body sections and within head (which is skipped)
- * we neither can have code or pre segments!
- */
- handleContentTag : function() {
- //lookahead head, body, html which means a lookahead of 4;
- this._currentSection = null;
- this._skipBlank();
- var tagName = this._fetchTagname();
-
- /*we try to avoid lookaheads here hence the shifting of tokens!*/
- if (tagName == this.tagNameStart) {
- /*either embedded into html */
- this.handleIdentifiedContent();
- //after the html tag is processed we can break from the first parsing stage
- this.tokenPos = this.tokens.length;
- } else if (tagName == "scri" || tagName == "styl") {
- //script must be handled separately since we can have embedded tags which must be ignored
- this.handleScriptStyle();
- } else {
- //unidentified content we deal with it by skipping to the tag end
- //and then be done with it!
- this.skipToTagEnd();
- }
- },
-
- /**
- * script skipping routine...
- * we skip automatically over embedded scripts
- * and tags within strings and comments
- * so that we do not trigger against embedded tags in script sections
- * of the head!
- *
- *
- */
- handleScriptStyle : function() {
- this.skipToTagEnd();
- //singleToken??
- if (this.tokens[this._tokenPos - 1] == "/" && this.tokens[this._tokenPos] == ">") {
- return;
- }
- //lets skip until we hit < by ignoring embedded strings and comments
- do {
- this._skipBlank(1);
- var token = this._getCurrentToken();
- switch (token) {
- case "\'" || "'":
- this.handleString(token);
- break;
- case "/" :
- this.handleJSComment();
- break;
- }
-
- } while (this.tokens[this._tokenPos] != "<");
- //now we should be at the end of the script tag at any circumstances!
- this.skipToTagEnd();
- },
- /**
- * javascript comment handler
- * we have to check for escape sequences so that we do not trigger
- * accidentally the comment parsing within embedded regular expressions
- * which means we have to prefetch and backtrack one token!
- * \/* should not start a comment neither should \//
- * if someone places this in the middle of the code
- * then oh well, syntax error on the javascript side
- * we cannot do anything about it
- */
- handleJSComment : function() {
- var token = this._getCurrentToken();
- var prefetchToken = this.tokens[this._tokenPos + 1];
- var backtrackToken = this.tokens[this._tokenPos - 1];
- var backtrackToken2 = this.tokens[this._tokenPos - 2];
-
- //comment condition == either /* or // with no \ in backtrack or \\ in backtrack!
- var backTrackIsComment = backtrackToken != '\\' || (backtrackToken == '\\' && backtrackToken2 == '\\');
- if (!backTrackIsComment) {
- return;
- }
-
- var singleLineComment = prefetchToken == '/';
- var multiLineComment = prefetchToken == "*";
-
- if (singleLineComment) {
- while (this._tokenPos < this.tokens.length && this._getCurrentToken() != "\n") {
- this._tokenPos++;
- }
-
- } else if (multiLineComment) {
- this._skipBlank(1);
- while (this._tokenPos < this.tokens.length) {
- this._skipBlank(1);
- token = this._getCurrentToken();
- prefetchToken = this.tokens[this._tokenPos + 1];
- if (token == "*" && prefetchToken == "/") {
- return;
- }
- }
- }
- },
+ //no need for ll parsing a handful of indexofs instead of slower regepx suffices
- /*----------------- reverse parsing --------*/
+ var proposedTagStartPos = theString.indexOf("<"+tagNameStart);
- /**
- * the end block tos a bottom up resolution of the parsing process
- * via an inverted tag name to look for
- */
- handleEndBlock : function() {
- for (; this._tokenPos >= 0; this._tokenPos += this._tokenForward) {
- this._skipBlank(0);
- var token = this._getCurrentToken();
- if (token == ">") {
- this.handleEndTagPart();
+ while(this._contentStart == -1 && proposedTagStartPos != -1) {
+ if(this.checkBackForComment(theString, proposedTagStartPos)) {
+ this._tagStart = proposedTagStartPos;
+ this._contentStart = proposedTagStartPos+theString.substring(proposedTagStartPos).indexOf(">")+1;
}
- }
- },
-
- handleEndTagPart : function() {
- this._tagEnd = this._tokenPos;
- this._skipBlank(1);
-
- if (this._tokenPos < 0) {
- throw new Error("Document end reached prematurely");
- }
- var token = this._getCurrentToken();
-
- //we can assume we are outside of the html or body sections
- //se we only have to check for comments for the reverse parsing!
- switch (token) {
- case "-":
-
- this.handleComment(true);
- break;
-
- default: this.handleContentEnd();
- }
-
- },
-
- handleContentEnd : function() {
- var tagFound = false;
- var first = true;
- for (; this._tokenPos >= 0; this._skipBlank(1)) {
- if (first && !tagFound) {
- var tagName = this._fetchTagname();
- if (tagName == this.tagNameEnd) {
- tagFound = true;
- }
- first = false;
- } else if (tagFound && this.tokens[this._tokenPos] == "<") {
- this._contentEnd = this._tokenPos - 1;
- this._tokenPos = -1;
- return;
- } else if (this.tokens[this._tokenPos] == "<") {
- this._tokenPos += 1;
- return;
- }
-
- }
- },
-
- /*----------------- helpers ----------------*/
- /**
- * skips the current tag definition until the end is reached
- *
- * @param analyzeAttributes if set to true we will end up with
- * a map of determined key value pairs which we then can further process
- * otherwise the key value pair determination is ignored!
- */
- skipToTagEnd : function(analyzeAttributes) {
-
- var token = this._getCurrentToken();
- //faster shortcut for tags which have to be nont analyzed
- if (!analyzeAttributes) {
- while (token != ">") {
- if (this._isStringStart()) {
- this._tokenPos += this._tokenForward;
- return this.handleString(token)
- }
- this._skipBlank(1);
- token = this._getCurrentToken();
- }
-
- return null;
+ proposedTagStartPos = theString.substring(proposedTagStartPos+tagNameStart.length+2).indexOf("<"+tagNameStart);
}
- //analyze part
-
- var keyValuePairs = {};
- var currentWord = [];
- while (this.tokens[this._tokenPos] != ">") {
- currentWord = this._fetchWord();
- token = this._getCurrentToken();
-
- if (token == "=") {
- this._tokenPos += this._tokenForward;
- keyValuePairs[currentWord] = this._fetchWord();
- } else {
- keyValuePairs[currentWord] = null;
+ var proposedEndTagPos = theString.lastIndexOf("</"+tagNameStart);
+ while(this._contentEnd == -1 && proposedEndTagPos > 0) {
+ if(this.checkForwardForComment(theString, proposedEndTagPos)) {
+ this._tagEnd = proposedEndTagPos;
+ this._contentEnd = proposedEndTagPos;
}
- this._tokenPos += this._tokenForward;
+ proposedTagStartPos = theString.substring(proposedTagStartPos-tagNameStart.length-2).lastIndexOf("</"+tagNameStart);
}
- return keyValuePairs;
- },
-
- /**
- * fetches a word which either can be a string or
- * a sequence of non string characters until either = or > or blank is reached!
- */
- _fetchWord : function() {
- this._skipBlank(0);
- var result = [];
-
- var token = this._getCurrentToken();
- while ((!this._isBlank()) && token != "=" && token != ">") {
- if (this._isStringStart()) {
- this._tokenPos += this._tokenForward;
- return this.handleString(token)
- }
-
- result.push(token);
- this._tokenPos += this._tokenForward;
- token = this._getCurrentToken();
+ if(this._contentStart != -1 && this._contentEnd != -1) {
+ return theString.substring(this._contentStart, this._contentEnd);
}
- return result.join("");
- },
-
- _isBlank : function() {
- var token = this._getCurrentToken();
- return token == " " && token == "\t" && token == "\n";
+ return null;
},
+
+ checkForwardForComment: function(theStr, tagPos) {
+ var toCheck = theStr.substring(tagPos);
+ var firstBeginComment = toCheck.indexOf("<!--");
+ var firstEndComment = toCheck.indexOf("-->");
- /**
- * we can make speedup shorcut assumptions here
- * becase we only try to either identfy head
- * html or body!
- */
- handleIdentifiedContent : function() {
-
- this.tagAttributes = this.skipToTagEnd(true);
- //TODO trace down the attributes and store them
- //they must be key value pairs
-
- if (this.tokens[this._tokenPos - 1] == "/" && this.tokens[this._tokenPos] == ">") {
- this._contentStart = -1;
- this._contentEnd = -1;
- /*we move to the end*/
- } else {
- this._contentStart = this._tokenPos + 1;
+ var firstBeginCDATA = toCheck.indexOf("<[CDATA[");
+ var firstEndCDATA = toCheck.indexOf("]]>");
+
+ if(this.isValidPositionCombination(firstBeginComment, firstEndComment, firstBeginCDATA, firstEndCDATA)) {
+ return true;
}
- },
- /**
- * returns true if the current token is a string start!
- */
- _isStringStart : function() {
- var backTrack = (this._tokenPos > 0) ? this.tokens[this._tokenPos - 1] : null;
- var token = this.tokens[this._tokenPos];
- return (token == "'" || token == '"') && backTrack != "\\";
+ return firstBeginComment <= firstEndComment && firstBeginCDATA <= firstEndCDATA;
},
- /**
- * skips a string section cintentwise no matter how many other strings
- * are embedded (uses backtracking to check for escapes)
- *
- * @param {String} stringToken the string token to skip!
- * @return the string value without the enclosing hypenations to be processed later on
- */
- handleString : function(stringToken) {
- var backTrack = null;
- var resultString = [];
- while (this.tokens[this._tokenPos] != stringToken || backTrack == "\\") {
- backTrack = this._getCurrentToken();
- resultString.push(backTrack);
- this._tokenPos += this._tokenForward;
- if (this._tokenPos >= this.tokens.length) {
- throw Error("Invalid html string opened but not closed");
- }
- }
- this._getCurrentToken();
- return resultString.join("");
- },
+ checkBackForComment: function(theStr, tagPos) {
+ var toCheck = theStr.substring(tagPos);
+ var lastBeginComment = toCheck.lastIndexOf("<!--");
+ var lastEndComment = toCheck.lastIndexOf("-->");
- _assertValues : function(assertValues) {
+ var lastBeginCDATA = toCheck.lastIndexOf("<[CDATA[");
+ var lastEndCDATA = toCheck.lastIndexOf("]]>");
- for (var loop = 0; loop < assertValues.length; loop++) {
- this._assertValue(assertValues[loop]);
- this._skipBlank(1);
- }
- },
- _assertValue : function(expectedToken) {
- var token = this._getCurrentToken();
- this._assertLength();
- if (token != expectedToken) {
- throw Error("Invalid Token " + expectedToken + " was expected instead of " + token);
+ if(this.isValidPositionCombination(lastBeginComment, lastEndComment, lastBeginCDATA, lastEndCDATA)) {
+ //TODO we have to handle the embedded cases, for now we leave them out
+ return true;
}
- return token;
},
- _assertLength : function() {
- if (this._tokenPos >= this.tokens.length) {
- throw Error("Invalid html comment opened but not closed");
- }
+ isValidPositionCombination: function(pos1, pos2, pos3, pos4) {
+ return pos1 <= pos2 && pos3 <= pos4;
},
- /**
- * nested comments are not allowed hence we
- * skip them!
- * comment == "<!--" [-->] "-->"
- */
- handleComment : function(reverse) {
- this._assertValues(["-","-"]);
- reverse = !!reverse;
-
- while (this._tokenPos < this.tokens.length - 3) {
- //lookahead3, to save some code
- var token = this._getCurrentToken();
- var backTrackBuf = [];
-
- if (token == "-") {
- backTrackBuf.push(token);
- this._skipBlank(1);
- token = this._getCurrentToken();
- backTrackBuf.push(token);
- this._skipBlank(1);
- token = this._getCurrentToken();
- backTrackBuf.push(token);
-
- if (reverse) {
- this._skipBlank(1);
- token = this._getCurrentToken();
- backTrackBuf.push(token);
- }
- var sBackTrackBuf = backTrackBuf.join("");
-
- if (reverse && sBackTrackBuf == "<!--") {
- return;
- } else if (!reverse && sBackTrackBuf == "-->") {
- return;
- }
- } else {
- this._skipBlank(1);
- }
- }
- },
-
- /**
- * fetches and stores the current token
- */
- _getCurrentToken : function() {
- return this.tokens[this._tokenPos];
+ isFullyEmbedded: function(pos1, pos2, embedPos1, embedPos2) {
+ return embedPos1 < pos1 < pos2 < embedPos2;
},
- /**
- * skip blank until the next token is found
- * @param skipVal the minimum skip forward to happen
- * 1 means it skips 1 no matter if the current token is a blank or not!
- *
- */
- _skipBlank : function(skipVal) {
- var len = this.tokens.length;
- if (!skipVal) {
- skipVal = 0;
- }
-
- for (this._tokenPos += (skipVal * this._tokenForward); this._tokenPos < len && this._tokenPos >= 0; this._tokenPos += this._tokenForward) {
- var token = this.tokens[this._tokenPos];
- if (token != " " && token != "\t" && token != "\n") {
- return;
- }
- }
- },
-
- _fetchTagname : function() {
- var tagName = [];
-
- //TODO make the tagname prefetch more generic
-
- tagName.push(this.tokens[this._tokenPos]);
- this._tokenPos += this._tokenForward;
- tagName.push(this._getCurrentToken());
- this._tokenPos += this._tokenForward;
- tagName.push(this._getCurrentToken());
- this._tokenPos += this._tokenForward;
- tagName.push(this._getCurrentToken());
- this._tokenPos += this._tokenForward;
-
- return tagName.join("").toLowerCase();
+ isPartiallyEmbedded: function(pos1, pos2, embedPos1, embedPos2) {
+ return embedPos1 < pos1 < embedPos2 < pos2 || pos1 < embedPos1 < pos2 < embedPos2 ;
}
});
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js?rev=959421&r1=959420&r2=959421&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Lang.js Wed Jun 30 20:24:21 2010
@@ -381,7 +381,7 @@ myfaces._impl.core._Runtime.singletonDel
return this.isString(theType) ? probe == typeof theType : probe instanceof theType;
},
-
+
objToArray: function(obj, offset, pack) {
//since offset is numeric we cannot use the shortcut due to 0 being false
@@ -408,7 +408,7 @@ myfaces._impl.core._Runtime.singletonDel
* foreach implementation utilizing the
* ECMAScript wherever possible
* with added functionality
- *
+ *
* @param arr the array to filter
* @param func the closure to apply the function to, with the syntax defined by the ecmascript functionality
* function (element<,key, array>)
@@ -416,14 +416,14 @@ myfaces._impl.core._Runtime.singletonDel
* @param scope (optional) the scope to apply the closure to
*/
arrForEach: function(arr, func /*startPos, scope*/) {
- var startPos = Number(arguments[2]) || 0;
+ var startPos = Number(arguments[2]) || 0;
var thisObj = arguments[3];
//check for an existing foreach mapping on array prototypes
if (Array.prototype.forEach) {
(startPos) ? arr.slice(startPos).forEach(func, thisObj) : arr.forEach(func, thisObj);
} else {
- startPos = (startPos < 0)? Math.ceil(startPos): Math.floor(startPos);
+ startPos = (startPos < 0) ? Math.ceil(startPos) : Math.floor(startPos);
if (typeof func != "function") {
throw new TypeError();
}
@@ -462,7 +462,7 @@ myfaces._impl.core._Runtime.singletonDel
throw new TypeError();
}
var ret = [];
- startPos = (startPos < 0)? Math.ceil(startPos): Math.floor(startPos);
+ startPos = (startPos < 0) ? Math.ceil(startPos) : Math.floor(startPos);
for (var cnt = startPos; cnt < arr.length; cnt++) {
if (thisObj) {
@@ -486,18 +486,18 @@ myfaces._impl.core._Runtime.singletonDel
* @param element the index to search for
*/
arrIndexOf: function(arr, element /*fromIndex*/) {
- if(!arr) return -1;
+ if (!arr) return -1;
var pos = Number(arguments[2]) || 0;
- if(Array.prototype.indexOf) {
+ if (Array.prototype.indexOf) {
return arr.indexOf(element, pos);
}
//var cnt = this._space;
var len = arr.length;
- pos = (pos < 0)? Math.ceil(pos): Math.floor(pos);
+ pos = (pos < 0) ? Math.ceil(pos) : Math.floor(pos);
//if negative then it is taken from as offset from the length of the array
- if(pos < 0) {
+ if (pos < 0) {
pos += len;
}
while (pos < len && arr[pos] !== element) {
@@ -575,6 +575,105 @@ myfaces._impl.core._Runtime.singletonDel
}
ret.push(delimiter);
return ret.join("");
+ },
+
+
+ parseXML: function(txt) {
+ var parser = null, xmlDoc = null;
+ if (window.DOMParser)
+ {
+ parser = new DOMParser();
+ xmlDoc = parser.parseFromString(txt, "text/xml");
+ }
+ else // Internet Explorer
+ {
+ xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.async = "false";
+ xmlDoc.loadXML(txt);
+ }
+ return xmlDoc;
+ },
+
+ serializeXML: function(xmlNode) {
+ if (xmlNode.xml) return xmlNode.xml; //IE
+ //rest of the world
+ return (new XMLSerializer()).serializeToString(xmlNode);
+ },
+
+ serializeChilds: function(xmlNode) {
+ var buffer = [];
+ if (!xmlNode.childNodes) return "";
+ for (var cnt = 0; cnt < xmlNode.childNodes.length; cnt++) {
+ buffer.push(this.serializeXML(xmlNode.childNodes[cnt]));
+ }
+ return buffer.join("");
+ },
+ isXMLParseError: function(xmlContent) {
+ var findParseError = function(node) {
+ if (!node || !node.childNodes) return false;
+ for (var cnt = 0; cnt < node.childNodes.length; cnt++) {
+ var childNode = node.childNodes[cnt];
+ if (childNode.tagName && childNode.tagName == "parsererror") return true;
+ }
+ return false;
+ };
+ return !xmlContent ||
+ (this.exists(xmlContent, "parseError.errorCode") && xmlContent.parseError.errorCode != 0) ||
+ findParseError(xmlContent)
+
}
-});
+ /* not used for now
+ parseHTML: function(txt) {
+ var frame = document.getElementById("parsing-frame");
+ if (frame) {
+ var frame = document.getElementById("parsing-frame");
+ frame.parentNode.removeChild(frame);
+ }
+
+ try {
+ // create frame
+ var frame = document.createElement("iframe"); // iframe (or browser on older Firefox)
+ frame.setAttribute("id", "parsing-frame");
+ frame.setAttribute("name", "parsing-frame");
+ frame.setAttribute("type", "content");
+ frame.setAttribute("collapsed", "true");
+ frame.setAttribute("display", "none");
+ document.body.appendChild(frame);
+ // or
+ // document.documentElement.appendChild(frame);
+
+ // set restrictions as needed
+ if (frame.webNavigation) {
+ frame.webNavigation.allowAuth = false;
+ frame.webNavigation.allowImages = false;
+ frame.webNavigation.allowJavascript = false;
+ frame.webNavigation.allowMetaRedirects = true;
+ frame.webNavigation.allowPlugins = false;
+ frame.webNavigation.allowSubframes = false;
+ }
+
+ var doc = frame.document;
+ if (frame.contentDocument)
+ doc = frame.contentDocument; // For NS6
+ else if (frame.contentWindow)
+ doc = frame.contentWindow.document; // For IE5.5 and IE6
+
+ // Put the content in the iframe
+ doc.open();
+ doc.writeln(txt);
+ doc.close();
+
+ return doc;
+ } finally {
+ if (frame) {
+ var frame = document.getElementById("parsing-frame");
+ frame.parentNode.removeChild(frame);
+ }
+ }
+ // listen for load
+ }
+ */
+
+})
+ ;
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js?rev=959421&r1=959420&r2=959421&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/Impl.js Wed Jun 30 20:24:21 2010
@@ -382,6 +382,7 @@ myfaces._impl.core._Runtime.singletonExt
getProjectStage : function() {
/* run through all script tags and try to find the one that includes jsf.js */
var scriptTags = document.getElementsByTagName("script");
+ var getConfig = myfaces._impl.core._Runtime.getGlobalConfig;
for (var i = 0; i < scriptTags.length; i++)
{
if (scriptTags[i].src.search(/\/javax\.faces\.resource\/jsf\.js.*ln=javax\.faces/) != -1)
@@ -401,13 +402,15 @@ myfaces._impl.core._Runtime.singletonExt
}
else
{
- //we found the script, but there was no stage parameter --> Production
- return "Production";
+ //we found the script, but there was no stage parameter -- Production
+ //(we also add an override here for testing purposes, the default, however is Production)
+ return getConfig("projectStage", "Production");
+ //return "Production";
}
}
}
/* we could not find anything valid --> return the default value */
- return "Production";
+ return getConfig("projectStage", "Production");
},
/**
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js?rev=959421&r1=959420&r2=959421&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/core/_Runtime.js Wed Jun 30 20:24:21 2010
@@ -463,7 +463,7 @@ if (!myfaces._impl.core._Runtime) {
if (key && typeof delFn == "function") {
proto[key] = function(/*arguments*/) {
var ret = delFn.apply(delegateObj, arguments);
- if ('undefined' != ret) return ret;
+ if ('undefined' != typeof ret) return ret;
};
}
})(key, delegateObj[key]);
Modified: myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js?rev=959421&r1=959420&r2=959421&view=diff
==============================================================================
--- myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js (original)
+++ myfaces/core/trunk/api/src/main/javascript/META-INF/resources/myfaces/_impl/xhrCore/_AjaxResponse.js Wed Jun 30 20:24:21 2010
@@ -88,14 +88,17 @@ myfaces._impl.core._Runtime.extendClass(
_Impl.sendError(request, context, myfaces._impl.core.Impl.EMPTY_RESPONSE);
return;
}
+ //check for a parseError under certain browsers
+
var xmlContent = request.responseXML;
//ie6+ keeps the parsing response under xmlContent.parserError
//while the rest of the world keeps it as element under the first node
- if ((this._Lang.exists(xmlContent, "parseError.errorCode") && xmlContent.parseError.errorCode != 0) || this._Lang.equalsIgnoreCase(xmlContent.firstChild.tagName, "parsererror")) {
- //TODO improve error name and message sending here
+
+
+ if ( this._Lang.isXMLParseError(xmlContent)) {
_Impl.sendError(request, context, myfaces._impl.core.Impl.MALFORMEDXML);
return;
}
@@ -170,7 +173,7 @@ myfaces._impl.core._Runtime.extendClass(
_setVSTOuterForm: function(elem) {
var viewStateField = this._Dom.findFormElement(elem, this.P_VIEWSTATE);
if (null != viewStateField) {
- this._Dom.setAttribute(viewStateField, "value", this.appliedViewState);
+ this._Dom.setAttribute(viewStateField,"value", this.appliedViewState);
}
},
@@ -352,6 +355,8 @@ myfaces._impl.core._Runtime.extendClass(
switch (node.getAttribute('id')) {
case this.P_VIEWROOT:
+ cDataBlock = cDataBlock.substring(cDataBlock.indexOf("<html"));
+ this._replaceHead(request, context, cDataBlock);
var resultNode = this._replaceBody(request, context, cDataBlock);
if (resultNode) {
this._pushOperationResult(resultNode);
@@ -360,7 +365,7 @@ myfaces._impl.core._Runtime.extendClass(
case this.P_VIEWHEAD:
//we cannot replace the head, almost no browser allows this, some of them throw errors
//others simply ignore it or replace it and destroy the dom that way!
- throw new Error("Head cannot be replaced, due to browser deficiencies!");
+ this._replaceHead(request, context, cDataBlock);
break;
case this.P_VIEWBODY:
@@ -404,6 +409,32 @@ myfaces._impl.core._Runtime.extendClass(
},
+ _replaceHead: function(request, context, newData) {
+ var doc = this._Lang.parseXML(newData);
+ var newHead = null;
+ if(this._Lang.isXMLParseError(doc)) {
+ //the standard xml parser failed we retry with the stripper
+ var parser = new (myfaces._impl.core._Runtime.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
+ var headData = parser.parse(newData, "head");
+ newHead = this._Lang.parseXML("<root>"+headData+"</root>");
+ if(this._Lang.isXMLParseError(newHead)) {
+ //we give up no further fallbacks
+ this._Impl.sendError(request, context, _Impl.MALFORMEDXML, _Impl.MALFORMEDXML, "Error in PPR Insert, before id or after id must be present");
+ return;
+ }
+ } else {
+ //parser worked we go on
+ newHead = doc.getElementsByTagName("head")[0];
+ }
+
+ //since we are xml enabled here we probably can walk over it via xml <head> ... </head> normally is valid xml
+ //the ie tricks with form etc... do not work out, so we have to rely on internal xml parsing
+ //prestripping the body should reduce the failure rate of this method
+ ///var xmlData = this._Lang.parseXML("<root>"+headData+"</root>");
+ this._Dom.runScripts(newHead, true);
+ },
+
+
/**
* special method to handle the body dom manipulation,
* replacing the entire body does not work fully by simply adding a second body
@@ -428,16 +459,32 @@ myfaces._impl.core._Runtime.extendClass(
//the contextualFragment trick does not work on the body tag instead we have to generate a manual body
//element and then add a child which then is the replacement holder for our fragment!
- //TODO we probably should try to offload this to the browser first via the integrated xml parsing
- //and if it fails revert to our internal parser
- var bodyData = parser.parse(newData, "body");
+ //Note, we also could offload this to the browser,
+ //but for now our parser seems to be faster than the browser offloading method
+ //and also does not interfere on security level
+ //the browser offloading methods would be first to use the xml parsing
+ //and if that fails revert to a hidden iframe
+ //var bodyData = parser.parse(newData, "body");
+ var bodyData = null;
+ var doc = this._Lang.parseXML(newData);
+ if(this._Lang.isXMLParseError(doc)) {
+ //the standard xml parser failed we retry with the stripper
+ var parser = new (myfaces._impl.core._Runtime.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
+ bodyData = parser.parse(newData, "body");
+ } else {
+ //parser worked we go on
+ var newBodyData = doc.getElementsByTagName("body")[0];
+ bodyData = this._Lang.serializeChilds(newBodyData);
+ for (var cnt = 0; cnt < newBodyData.attributes.length; cnt++) {
+ var value = newBodyData.attributes[cnt].value;
+ if(value)
+ this._Dom.setAttribute(newBody, newBodyData.attributes[cnt].name, value);
+ }
+ }
+
bodyParent.replaceChild(newBody, oldBody);
var returnedElement = this._replaceElement(request, context, placeHolder, bodyData);
- for (var key in parser.tagAttributes) {
- var value = parser.tagAttributes[key];
- this._Dom.setAttribute(newBody, key, value);
- }
return returnedElement;
}
,