Author: max
Date: 2007-08-03 15:29:00 -0700 (Fri, 03 Aug 2007)
New Revision: 5928
Modified:
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/core/LzNode.lzs
openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/services/LzCSSStyle.js
openlaszlo/branches/wafflecone/test/lztest/lztest-textheight.lzx
Log:
ehange 20070803-maxcarlson-n by [EMAIL PROTECTED] on 2007-08-03 15:22:00 PDT
in /Users/maxcarlson/openlaszlo/wafflecone
for http://svn.openlaszlo.org/openlaszlo/branches/wafflecone
Summary: More LFC optimization/simplification
New Features:
Bugs Fixed: LPP-4414 - Improve startup performance
Technical Reviewer: ben
QA Reviewer: promanik
Doc Reviewer: (pending)
Documentation:
Release Notes:
Details: lztest-textheight.lzx - label multiline inputtext test better.
LzCSSStyle.js - Remove recursion, correct getPropertyValueFor() warnings,
simplify _selectorApplies().
LzNode.lzs - Clean up getUID().
Tests:
http://localhost:8080/wafflecone/test/style/metasuite.lzx?lzr=swf8&debug=true
passes (with new warnings!) and silver/main.lzx?lzr=dhtml&lzt=html is slightly
faster (with the same number of method calls)
Modified: openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/core/LzNode.lzs
===================================================================
--- openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/core/LzNode.lzs
2007-08-03 22:27:48 UTC (rev 5927)
+++ openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/core/LzNode.lzs
2007-08-03 22:29:00 UTC (rev 5928)
@@ -47,6 +47,7 @@
* @param Boolean instcall
*/
function initialize ( parent , attrs , children , instcall ){
+ this.__LZUID = "__U" + ++LzNode.__UIDs;
this.__LZdeferDelegates = true;
var qpos = LzDelegate.__LZdelegatesQueue.length;
super.initialize.apply(this, arguments);
@@ -1679,18 +1680,16 @@
}while ( sview != canvas );
}
+/**
+ * @access private
+ */
+static var __UIDs = 0;
-static var UIDs = 0;
-
/**
* Returns the unique ID of the node.
* @return String: A string representing a unique ID for the node.
*/
function getUID (){
- if ( this.__LZUID == null ){
- this.__LZUID = "__U" + ++LzNode.UIDs;
- }
-
return this.__LZUID;
}
Modified: openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/services/LzCSSStyle.js
===================================================================
--- openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/services/LzCSSStyle.js
2007-08-03 22:27:48 UTC (rev 5927)
+++ openlaszlo/branches/wafflecone/WEB-INF/lps/lfc/services/LzCSSStyle.js
2007-08-03 22:29:00 UTC (rev 5928)
@@ -28,7 +28,7 @@
if ( !this.specificity ) {
//need to treat compound selectors differently
- if ( this.parsed.type == LzCSSStyle._selTypes.compound ){
+ if ( this.parsed.type == LzCSSStyle._sel_compound ){
for ( var i = 0; i < this.parsed.length; i++ ){
this.specificity += LzCSSStyle.getSelectorSpecificity(
this.parsed[ i ] );
}
@@ -70,8 +70,6 @@
return 1 ;
}
-LzCSSStyleRule.prototype.__pvcache = {};
-
var LzCSSStyle = {};
LzCSSStyle.getComputedStyle = function ( node ){
@@ -82,97 +80,96 @@
/** @access private */
LzCSSStyle.__LZRuleCache = {};
+LzCSSStyle.__LZPropertyCache = {};
//LzCSSStyle.time1 = 0;
-LzCSSStyle.getPropertyValueFor = function ( node , pname ){
+LzCSSStyle.getPropertyValueFor = function ( initialnode , pname ){
//Debug.warn("node: %w, pname: %w, rules: %w\n", node, pname, this._rules);
//var t = getTimer();
- if (!node) return;
- var uid = node.getUID();
- var val = LzCSSStyleRule.prototype.__pvcache[uid + pname];
- if (val) return val;
- var rules = this.__LZRuleCache[ uid ];
- if ( !rules ) {
- rules = new Array();
- var r;
- for ( var i = this._rules.length -1; i >=0; i-- ){
- r = this._rules[ i ];
- var rp = r.parsed;
- if ( rp.type == 1 ||
- (rp.type == 2 && rp.id == node.id) ||
- (rp.type == 3 && (((rp.classname in lz) && (node instanceof
lz[ rp.classname ])) || ( (rp.classname in global) && (node instanceof global[
rp.classname ])))) ||
- (rp.type == 5 && node[ rp.attrname ] == rp.attrvalue) ||
- (rp.type == 6 && node[ rp.attrname ] == rp.attrvalue &&
(((rp.classname in lz) && (node instanceof lz[ rp.classname ])) || (
(rp.classname in global) && (node instanceof global[ rp.classname ])))) ||
- (rp.type == 4 && this._selectorApplies( r, rp, node ))){
- rules.push(r);
- }
- }
+ if (!initialnode || !pname) return;
- //now look at any preprocessed rules
- // NOTE:
- // it would be nice to just use (node.name) as the condition, but
- // swf6 does not obey obey the ECMA string->boolean coercion
specification.
- // As a workaround, we compare node.name to null, thereby ensuring we
get a boolean
- // in swf6 or ECMA-compatible runtimes
- var pprules = (node.name != null) ? this._nameRules[ node.name ] :
null;
- if ( pprules ){
- //same code as above, but inline to avoid function call overhead
- for ( var i = pprules.length -1; i >=0; i-- ){
- r = pprules[ i ];
+ var node = initialnode;
+ while (node != canvas) {
+ var uid = node.__LZUID;
+ var val = this.__LZPropertyCache[uid + pname];
+ if (val != null) return val;
+
+ var rules = this.__LZRuleCache[ uid ];
+ if ( !rules ) {
+ rules = new Array();
+ var r;
+ for ( var i = this._rules.length -1; i >=0; i-- ){
+ r = this._rules[ i ];
var rp = r.parsed;
- if ( rp.type == 1 ||
- (rp.type == 2 && rp.id == node.id) ||
- (rp.type == 3 && (((rp.classname in lz) && (node instanceof
lz[ rp.classname ])) || ( (rp.classname in global) && (node instanceof global[
rp.classname ])))) ||
- (rp.type == 5 && node[ rp.attrname ] == rp.attrvalue) ||
- (rp.type == 6 && node[ rp.attrname ] == rp.attrvalue &&
(((rp.classname in lz) && (node instanceof lz[ rp.classname ])) || (
(rp.classname in global) && (node instanceof global[ rp.classname ])))) ||
- (rp.type == 4 && this._selectorApplies( r, rp, node ))){
+ if ( rp.type == this._sel_star ||
+ (rp.type == this._sel_id && rp.id == node.id) ||
+ (rp.type == this._sel_tag && (((rp.classname in lz) &&
(node instanceof lz[ rp.classname ])) || ( (rp.classname in global) && (node
instanceof global[ rp.classname ])))) ||
+ (rp.type == this._sel_attribute && node[ rp.attrname ] ==
rp.attrvalue) ||
+ (rp.type == this._sel_tagAndAttr && node[ rp.attrname ] ==
rp.attrvalue && (((rp.classname in lz) && (node instanceof lz[ rp.classname ]))
|| ( (rp.classname in global) && (node instanceof global[ rp.classname ])))) ||
+ (rp.type == this._sel_compound && this._selectorApplies(
rp, node ))){
rules.push(r);
}
}
- }
-
- //sort match rules by their specificities
- //first tell the sort function who this is being sorted for; the sort
- //depends not only on the rules, but also on the specificity of the
- //class selector, if one is present
- rules.sort(this.__compareSpecificity);
-
- this.__LZRuleCache[ uid ] = rules;
- }
+ //now look at any preprocessed rules
+ // NOTE:
+ // it would be nice to just use (node.name) as the condition, but
+ // swf6 does not obey obey the ECMA string->boolean coercion
specification.
+ // As a workaround, we compare node.name to null, thereby ensuring
we get a boolean
+ // in swf6 or ECMA-compatible runtimes
+ var pprules = (node.name != null) ? this._nameRules[ node.name ] :
null;
+ if ( pprules ){
+ //same code as above, but inline to avoid function call
overhead
+ for ( var i = pprules.length -1; i >=0; i-- ){
+ r = pprules[ i ];
+ var rp = r.parsed;
+ if ( rp.type == this._sel_star ||
+ (rp.type == this._sel_id && rp.id == node.id) ||
+ (rp.type == this._sel_tag && (((rp.classname in lz) &&
(node instanceof lz[ rp.classname ])) || ( (rp.classname in global) && (node
instanceof global[ rp.classname ])))) ||
+ (rp.type == this._sel_attribute && node[ rp.attrname ] ==
rp.attrvalue) ||
+ (rp.type == this._sel_tagAndAttr && node[ rp.attrname ] ==
rp.attrvalue && (((rp.classname in lz) && (node instanceof lz[ rp.classname ]))
|| ( (rp.classname in global) && (node instanceof global[ rp.classname ])))) ||
+ (rp.type == this._sel_compound && this._selectorApplies(
rp, node ))){
+ rules.push(r);
+ }
+ }
+ }
+
+ //sort match rules by their specificities
+ //first tell the sort function who this is being sorted for; the
sort
+ //depends not only on the rules, but also on the specificity of the
+ //class selector, if one is present
- //Debug.write("About to print rule array.")
- //LzCSSStyle._printRuleArray( rules );
-
- var l = rules.length;
- var pv = null;
- var i = 0;
- while ( i < l ) {
- var props = rules[i++].properties;
- if (pname in props) {
- var v = props[pname];
- LzCSSStyleRule.prototype.__pvcache[uid + pname] = v
- return v;
+ rules.sort(this.__compareSpecificity);
+
+ this.__LZRuleCache[ uid ] = rules;
}
- }
- ////this.time1 += getTimer() - t;
- if ( node == canvas ) return null;
- else {
- if ($debug) {
- // Fix for LPP-3024: if we're in debug mode, warn when CSS lookup
- // results in a null or undefined value. [bshine 08.03.2007]
- var answer = this.getPropertyValueFor(node.immediateparent, pname
);
- if (answer == null)
- Debug.warn("There is no CSS property %s for node %s", pname,
node);
- return answer;
- } else {
- return this.getPropertyValueFor(node.immediateparent, pname );
+ //Debug.write("About to print rule array.")
+ //LzCSSStyle._printRuleArray( rules );
+
+ var l = rules.length;
+ var i = 0;
+ while ( i < l ) {
+ var props = rules[i++].properties;
+ if (pname in props) {
+ val = props[pname];
+ this.__LZPropertyCache[uid + pname] = val;
+ break;
+ }
}
+ if (val != null) return val;
+
+ node = node.immediateparent;
+ ////this.time1 += getTimer() - t;
}
+ if ($debug) {
+ // Fix for LPP-3024: if we're in debug mode, warn when CSS lookup
+ // results in a null or undefined value. [bshine 08.03.2007]
+ Debug.warn("There is no CSS property %s for node %s", pname,
initialnode);
+ }
}
LzCSSStyle.getSelectorSpecificity = function ( parsedsel ){
@@ -186,17 +183,17 @@
count the number of element names and pseudo-elements in the selector (=
d)
*/
switch ( parsedsel.type ){
- case (this._selTypes.tag ):
- case (this._selTypes.star ):
+ case (this._sel_tag ):
+ case (this._sel_star ):
return 1;
- case (this._selTypes.id ):
+ case (this._sel_id ):
return 100;
- case (this._selTypes.attribute ):
+ case (this._sel_attribute ):
return 10;
- case (this._selTypes.tagAndAttr ):
+ case (this._sel_tagAndAttr ):
return 11;
}
}
@@ -220,8 +217,8 @@
// if *that* matches, then the descendant rule with closer selectors
// wins
- if ( rA.parsed.type == LzCSSStyle._selTypes.compound &&
- rB.parsed.type == LzCSSStyle._selTypes.compound ){
+ if ( rA.parsed.type == LzCSSStyle._sel_compound &&
+ rB.parsed.type == LzCSSStyle._sel_compound ){
//iterate through the compound selector arrays
//assume that the selector arrays are the same length, due to
//specificity. if they don't, or if all the comparisons match, then
@@ -275,142 +272,60 @@
/** @devnote this ideally would be two separate functions, but merging them
* and inlining the cases of the switch statement is a 2x speedup [awolff]
* @access private */
-LzCSSStyle._selectorApplies = function ( rule, rp , node ){
+LzCSSStyle._selectorApplies = function ( rp , node ){
//rp is the parsed selector
- var result;
- switch ( rp.type ){
- case (this._selTypes.star ):
- result = true;
- break;
+ var t = rp.type;
+ if ( t == this._sel_star ||
+ (t == this._sel_id && rp.id == node.id) ||
+ (t == this._sel_tag && (((rp.classname in lz) && (node instanceof lz[
rp.classname ])) || ( (rp.classname in global) && (node instanceof global[
rp.classname ])))) ||
+ (t == this._sel_attribute && node[ rp.attrname ] == rp.attrvalue) ||
+ (t == this._sel_tagAndAttr && node[ rp.attrname ] == rp.attrvalue &&
(((rp.classname in lz) && (node instanceof lz[ rp.classname ])) || (
(rp.classname in global) && (node instanceof global[ rp.classname ]))))) {
+ return true;
+ } else if (t == this._sel_compound) {
+ var curnode = node;
+ var sindex = rp.length -1;
+ var firstone = true;
- case (this._selTypes.id ):
- result = node.id == rp.id;
- break;
+ while (curnode != canvas){
+ var nrp = rp[sindex]
+ t = nrp.type;
-
- case (this._selTypes.tag ):
- result = ((rp.classname in lz) && (node instanceof lz[
rp.classname ]))
- || ( (rp.classname in global) && (node instanceof global[
rp.classname ]));
- break;
-
- case (this._selTypes.compound ):
- var curnode = node;
- var sindex = rp.length -1;
-
- var firstone = true;
- while ( curnode ){
- // inline this._selectorApplies here
- // this._selectorApplies( rule, rp[ sindex ], curnode )
- var nrp = rp[sindex]
-
- var iresult;
- switch ( nrp.type ){
- case (this._selTypes.star ):
- iresult = true;
- break;
-
- case (this._selTypes.id ):
- iresult = curnode.id == nrp.id;
- break;
-
-
- case (this._selTypes.tag ):
- iresult = ((nrp.classname in lz) && (curnode
instanceof lz[ nrp.classname ]))
- || ( (nrp.classname in global) && (curnode
instanceof global[ nrp.classname ]));
- break;
-
- case (this._selTypes.compound ):
- var icurnode = curnode;
- var sindex = nrp.length -1;
-
- var ifirstone = true;
- while ( icurnode ){
-
- var inrp = nrp[sindex]
- if ( inrp.type == 1 ||
- (inrp.type == 2 && inrp.id == icurnode.id) ||
- (inrp.type == 3 && (((inrp.classname in lz) &&
(icurnode instanceof lz[ inrp.classname ])) || ( (inrp.classname in global) &&
(icurnode instanceof global[ inrp.classname ])))) ||
- (inrp.type == 5 && icurnode[ inrp.attrname ]
== inrp.attrvalue) ||
- (inrp.type == 6 && icurnode[ inrp.attrname ]
== inrp.attrvalue && (((inrp.classname in lz) && (icurnode instanceof lz[
inrp.classname ])) || ( (inrp.classname in global) && (icurnode instanceof
global[ inrp.classname ])))) ||
- (inrp.type == 4 && this._selectorApplies(
rule, inrp, icurnode ))){
- if ( sindex-- == 0 ){
- iresult = true;
- break;
- }
- } else if ( ifirstone ){
- //if the last selector doesn't apply, then
bail -- we'll
- //come back for this when we recurse over the
parents in
- //getPropertyValueFor
- iresult = false;
- break;
- }
-
- if (icurnode == canvas) break;
- icurnode = icurnode.parent;
- ifirstone = false;
- }
- if (iresult == null) iresult = false;
- break;
-
- case (this._selTypes.attribute ):
- iresult = curnode[ nrp.attrname ] == nrp.attrvalue;
- break;
-
- case (this._selTypes.tagAndAttr ):
- if (curnode[ nrp.attrname ] == nrp.attrvalue) {
- iresult = ((nrp.classname in lz) && (curnode
instanceof lz[ nrp.classname ]))
- || ( (nrp.classname in global) && (curnode
instanceof global[ nrp.classname ]));
- }
- if (iresult == null) iresult = false;
- break;
+ if ( t == this._sel_star ||
+ (t == this._sel_id && nrp.id == curnode.id) ||
+ (t == this._sel_tag && (((nrp.classname in lz) && (curnode
instanceof lz[ nrp.classname ])) || ( (nrp.classname in global) && (curnode
instanceof global[ nrp.classname ])))) ||
+ (t == this._sel_attribute && curnode[ nrp.attrname ] ==
nrp.attrvalue) ||
+ (t == this._sel_tagAndAttr && curnode[ nrp.attrname ] ==
nrp.attrvalue && (((nrp.classname in lz) && (curnode instanceof lz[
nrp.classname ])) || ( (nrp.classname in global) && (curnode instanceof global[
nrp.classname ])))) ||
+ (t == this._sel_compound && this._selectorApplies( nrp,
curnode ))){
+ if ( sindex-- == 0 ){
+ return true;
}
- // end inline
-
- if (iresult){
- if ( sindex-- == 0 ){
- result = true;
- break;
- }
- } else if ( firstone ){
- //if the last selector doesn't apply, then bail -- we'll
- //come back for this when we recurse over the parents in
- //getPropertyValueFor
- result = false;
- break;
- }
-
- if (curnode == canvas) break;
- curnode = curnode.parent;
- firstone = false;
+ } else if ( firstone ){
+ //if the last selector doesn't apply, then bail -- we'll
+ //come back for this when we recurse over the parents in
+ //getPropertyValueFor
+ return false;
}
- if (result == null) result = false;
- break;
- case (this._selTypes.attribute ):
- result = node[ rp.attrname ] == rp.attrvalue;
- break;
-
- case (this._selTypes.tagAndAttr ):
- if (node[ rp.attrname ] == rp.attrvalue) {
- result = ((rp.classname in lz) && (node instanceof lz[
rp.classname ]))
- || ( (rp.classname in global) && (node instanceof global[
rp.classname ]));
- }
- if (result == null) result = false;
- break;
+ curnode = curnode.parent;
+ firstone = false;
+ }
}
- return result;
}
/** @access private */
-LzCSSStyle._selTypes = {
- "unknown" : 0,
- "star" : 1, // *
- "id" : 2, // #gMyId
- "tag" : 3, // styledbox
- "compound" : 4, // E F
- "attribute" : 5, // [attr="val"]
- "tagAndAttr" : 6 // class[attr="val"]
-}
+LzCSSStyle._sel_unknown = 0;
+/** @access private */
+LzCSSStyle._sel_star = 1;
+/** @access private */
+LzCSSStyle._sel_id = 2;
+/** @access private */
+LzCSSStyle._sel_tag = 3
+/** @access private */
+LzCSSStyle._sel_compound = 4
+/** @access private */
+LzCSSStyle._sel_attribute = 5
+/** @access private */
+LzCSSStyle._sel_tagAndAttr = 6
/** @access private */
LzCSSStyle._rules = new Array();
@@ -432,7 +347,7 @@
var lastsel;
if ( sel instanceof Array ){
r.parsed = [];
- r.parsed.type = this._selTypes.compound;
+ r.parsed.type = this._sel_compound;
for ( var i = 0; i < sel.length; i++ ){
r.parsed.push( this._parseSelector( sel[ i ] ) );
}
@@ -445,8 +360,8 @@
//special treatment for rules that use name=
//we could do this pretty easily for ID if ID rules were common,
//or for other attibute names
- if ( ( lastsel.type == this._selTypes.attribute ||
- lastsel.type == this._selTypes.tagAndAttr )
+ if ( ( lastsel.type == this._sel_attribute ||
+ lastsel.type == this._sel_tagAndAttr )
&& lastsel.attrname == "name" ){
var aval = lastsel.attrvalue;
if ( !this._nameRules[ aval ] ) this._nameRules[ aval ] = [];
@@ -461,10 +376,10 @@
switch ( typeof ( sel ) ){
case "object":
if (sel.simpleselector) {
- sel.type = this._selTypes.tagAndAttr;
+ sel.type = this._sel_tagAndAttr;
sel.classname = this._normalizeClassname( sel.simpleselector );
} else
- sel.type = this._selTypes.attribute;
+ sel.type = this._sel_attribute;
return sel;
break;
case "string":
@@ -477,15 +392,15 @@
LzCSSStyle._parseStringSelector = function ( sel ){
var parsed = { };
if ( sel == "*" ) {
- parsed.type = this._selTypes.star;
+ parsed.type = this._sel_star;
} else {
var index = sel.indexOf("#");
if (index >= 0) {
// Assumption: there should only be one # in a selector
parsed.id = sel.substring(index + 1);
- parsed.type = this._selTypes.id;
+ parsed.type = this._sel_id;
} else {
- parsed.type = this._selTypes.tag;
+ parsed.type = this._sel_tag;
parsed.classname = this._normalizeClassname( sel );
}
Modified: openlaszlo/branches/wafflecone/test/lztest/lztest-textheight.lzx
===================================================================
--- openlaszlo/branches/wafflecone/test/lztest/lztest-textheight.lzx
2007-08-03 22:27:48 UTC (rev 5927)
+++ openlaszlo/branches/wafflecone/test/lztest/lztest-textheight.lzx
2007-08-03 22:29:00 UTC (rev 5928)
@@ -100,8 +100,8 @@
LzTestManager.assertEquals(48, it3.height, "inputtext4.height");
LzTestManager.assertEquals(38, it4.getAttribute("height"), "inputtext4
height");
LzTestManager.assertEquals(38, it4.height, "inputtext4.height");
- LzTestManager.assertEquals(52, it5.getAttribute("height"), "inputtext5
height");
- LzTestManager.assertEquals(52, it5.height, "inputtext5.height");
+ LzTestManager.assertEquals(52, it5.getAttribute("height"), "multiline
inputtext5 height");
+ LzTestManager.assertEquals(52, it5.height, "multiline inputtext5.height");
LzTestManager.assertEquals(38, it6.getAttribute("height"), "inputtext6
height");
LzTestManager.assertEquals(38, it6.height, "inputtext6.height");
LzTestManager.assertEquals(56, it7.getAttribute("height"), "multiline7
inputtext height");
@@ -141,8 +141,8 @@
LzTestManager.assertEquals(200, it3.width, "inputtext3.width");
LzTestManager.assertEquals(26, it4.getAttribute("width"), "inputtext4
width");
LzTestManager.assertEquals(26, it4.width, "inputtext4.width");
- LzTestManager.assertEquals(it5.parent.width, it5.getAttribute("width"),
"inputtext5 width");
- LzTestManager.assertEquals(it5.parent.width, it5.width,
"inputtext5.width");
+ LzTestManager.assertEquals(it5.parent.width, it5.getAttribute("width"),
"multiline inputtext5 width");
+ LzTestManager.assertEquals(it5.parent.width, it5.width, "multiline
inputtext5.width");
LzTestManager.assertEquals(26, it6.getAttribute("width"), "inputtext6
width");
LzTestManager.assertEquals(26, it6.width, "inputtext6.width");
_______________________________________________
Laszlo-checkins mailing list
[email protected]
http://www.openlaszlo.org/mailman/listinfo/laszlo-checkins