1 /* Licensed to the Apache Software Foundation (ASF) under one or more
  2  * contributor license agreements.  See the NOTICE file distributed with
  3  * this work for additional information regarding copyright ownership.
  4  * The ASF licenses this file to you under the Apache License, Version 2.0
  5  * (the "License"); you may not use this file except in compliance with
  6  * the License.  You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 
 17 /**
 18  * @namespace
 19  * @name window
 20  * @description Eval routines, depending on the browser.
 21  * <p/>
 22  * The problem solved in this class is the problem on how to perform
 23  * a global eval on multiple browsers. Some browsers auto eval themselves
 24  * they do not need to be called
 25  * <li>Some work with a window.eval.call(window,... </li>
 26  * <li>Others use simply execScript <li>
 27  * <li>Some others work only with the head appendix method
 28  * head.appendChild(<script...., head.removeChild(<script </li>
 29  * <p/>
 30  * Note: The code here already is precompressed because the compressor
 31  * fails on it, the deficits in readability will be covered by more comments
 32  *
 33  */
 34 
 35 
 36 if (!window.myfaces) {
 37     /**
 38      * @namespace
 39      * @name myfaces
 40      */
 41     var myfaces = new function() {
 42     };
 43     window.myfaces = myfaces;
 44 }
 45 
 46 /**
 47  * @memberOf myfaces
 48  * @namespace
 49  * @name _impl
 50  */
 51 myfaces._impl = (myfaces._impl) ? myfaces._impl : {};
 52 /**
 53  * @memberOf myfaces._impl
 54  * @namespace
 55  * @name core
 56  */
 57 myfaces._impl.core = (myfaces._impl.core) ? myfaces._impl.core :{};
 58 
 59 if (!myfaces._impl.core._EvalHandlers) {
 60     /**
 61      * @memberOf myfaces._impl.core
 62      * @namespace
 63      * @name _EvalHandlers
 64      */
 65     myfaces._impl.core._EvalHandlers = new function() {
 66         //the rest of the namespaces can be handled by our namespace feature
 67         //helper to avoid unneeded hitches
 68         /**
 69          * @borrows myfaces._impl.core._Runtime as _T
 70          */
 71         var _T = this;
 72 
 73         /*cascaded eval methods depending upon the browser*/
 74 
 75         /**
 76          * @function
 77          * @param code
 78 
 79          *
 80          * evals a script globally using exec script (ie6 fallback)
 81          * @param {String} code the code which has to be evaluated
 82          * @borrows myfaces._impl.core._Runtime as _T
 83          *
 84          * TODO eval if we cannot replace this method with the head appendix
 85          * method which is faster for ie this also would reduce our code
 86          * by a few bytes
 87          */
 88         _T._evalExecScript = function(code) {
 89             //execScript definitely only for IE otherwise we might have a custom
 90             //window extension with undefined behavior on our necks
 91             //window.execScript does not return anything
 92             //on htmlunit it return "null object"
 93             //_r == ret
 94             var _r = window.execScript(code);
 95             if ('undefined' != typeof _r && _r == "null" /*htmlunit bug*/) {
 96                 return null;
 97             }
 98             return _r;
 99         };
100 
101         /**
102          * flakey head appendix method which does not work in the correct
103          * order or at all for all modern browsers
104          * but seems to be the only method which works on blackberry correctly
105          * hence we are going to use it as fallback
106          *
107          * @param {String} code the code part to be evaled
108          * @borrows myfaces._impl.core._Runtime as _T
109          */
110         _T._evalHeadAppendix = function(code) {
111             //_l == location
112             var _l = document.getElementsByTagName("head")[0] || document.documentElement;
113             //_p == placeHolder
114             var _p = document.createElement("script");
115             _p.type = "text/javascript";
116             _p.text = code;
117             _l.insertBefore(_p, _l.firstChild);
118             _l.removeChild(_p);
119             return null;
120         };
121 
122         /**
123          * @name myfaces._impl.core._Runtime._standardGlobalEval
124          * @private
125          * @param {String} code
126          */
127         _T._standardGlobalEval = function(code) {
128             //fix which works in a cross browser way
129             //we used to scope an anonymous function
130             //but I think this is better
131             //the reason is some Firefox versions
132             // apply a wrong scope
133             //if we call eval by not scoping
134             //_U == "undefined"
135             var _U = "undefined";
136             var gEval = function () {
137                 //_r == retVal;
138                 var _r = window.eval.call(window, code);
139                 if (_U == typeof _r) return null;
140                 return _r;
141             };
142             var _r = gEval();
143             if (_U == typeof _r) return null;
144             return _r;
145         };
146 
147         /**
148          * global eval on scripts
149          * @param {String} c (code abbreviated since the compression does not work here)
150          * @name myfaces._impl.core._Runtime.globalEval
151          * @function
152          */
153         _T.globalEval = function(c) {
154             //TODO add a config param which allows to evaluate global scripts even if the call
155             //is embedded in an iframe
156             //We lazy init the eval type upon the browsers
157             //capabilities   
158             var _e = "_evalType";
159             var _w = window;
160             var _b = myfaces._impl.core._Runtime.browser;
161             //central routine to determine the eval method
162             if (!_T[_e]) {
163                 //execScript supported
164                 _T[_e] = _w.execScript ? "_evalExecScript" : null;
165 
166                 //in case of no support we go to the standard global eval  window.eval.call(window,
167                 // with Firefox fixes for scoping
168                 _T[_e] = _T[_e] ||(( _w.eval && (!_b.isBlackBerry ||_b.isBlackBerry >= 6)) ? "_standardGlobalEval" : null);
169 
170                 //this one routes into the hed appendix method
171                 _T[_e] = _T[_e] ||((_w.eval ) ? "_evalHeadAppendix" : null);
172             }
173             if (_T[_e]) {
174                 //we now execute the eval method
175                 return _T[_T[_e]](c);
176             }
177             //we probably have covered all browsers, but this is a safety net which might be triggered
178             //by some foreign browser which is not covered by the above cases
179             eval.call(window, c);
180             return null;
181         };
182 
183     };
184 }