Remove caching of style sheets in IE6 (cache may be invalid when there are multiple modules) Review at http://gwt-code-reviews.appspot.com/159804 Review by: jgw@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7694 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/client/StyleElement.java b/user/src/com/google/gwt/dom/client/StyleElement.java index 0a1da64..9f3e3d6 100644 --- a/user/src/com/google/gwt/dom/client/StyleElement.java +++ b/user/src/com/google/gwt/dom/client/StyleElement.java
@@ -40,6 +40,13 @@ } /** + * The CSS text. + */ + public final native String getCssText() /*-{ + return this.cssText; + }-*/; + + /** * Enables/disables the style sheet. * @deprecated use {@link #isDisabled()} instead */ @@ -73,6 +80,13 @@ }-*/; /** + * Sets the CSS text. + */ + public final native void setCssText(String cssText) /*-{ + this.cssText = cssText; + }-*/; + + /** * Enables/disables the style sheet. */ public final native void setDisabled(boolean disabled) /*-{
diff --git a/user/src/com/google/gwt/dom/client/StyleInjector.java b/user/src/com/google/gwt/dom/client/StyleInjector.java index c1dabcd..673d6ac 100644 --- a/user/src/com/google/gwt/dom/client/StyleInjector.java +++ b/user/src/com/google/gwt/dom/client/StyleInjector.java
@@ -17,8 +17,6 @@ import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; -import com.google.gwt.core.client.JsArray; -import com.google.gwt.core.client.JsArrayInteger; import com.google.gwt.core.client.JsArrayString; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; @@ -85,14 +83,29 @@ */ public static class StyleInjectorImplIE extends StyleInjectorImpl { - /* - * TODO(bobv) : Talk to scottb about being able to read this out of the - * module xml file as a configuration-property to handle cases where - * multiple GWT modules are living in the same page. + /** + * The maximum number of style tags that can be handled by IE. */ private static final int MAX_STYLE_SHEETS = 30; - private static final JsArray<StyleElement> STYLE_ELEMENTS = JavaScriptObject.createArray().cast(); - private static final JsArrayInteger STYLE_ELEMENT_LENGTHS = JavaScriptObject.createArray().cast(); + + /** + * A cache of the lengths of the current style sheets. A value of 0 + * indicates that the length has not yet been retrieved. + */ + private static int[] styleSheetLengths = new int[MAX_STYLE_SHEETS]; + + private static native int getDocumentStyleCount() /*-{ + return $doc.styleSheets.length; + }-*/; + + private static native StyleElement getDocumentStyleSheet(int index) /*-{ + return $doc.styleSheets[index]; + }-*/; + + private static native int getDocumentStyleSheetLength(int index) /*-{ + return $doc.styleSheets[index].cssText.length; + }-*/; + public native void appendContents(StyleElement style, String contents) /*-{ style.cssText += contents; @@ -100,89 +113,81 @@ @Override public StyleElement injectStyleSheet(String contents) { - int idx = STYLE_ELEMENTS.length(); - if (getDocumentStyleCount() < MAX_STYLE_SHEETS) { + int numStyles = getDocumentStyleCount(); + if (numStyles < MAX_STYLE_SHEETS) { // Just create a new style element and add it to the list - StyleElement style = createElement(); - setContents(style, contents); - STYLE_ELEMENTS.set(idx, style); - STYLE_ELEMENT_LENGTHS.set(idx, contents.length()); - return style; + return createNewStyleSheet(contents); } else { /* * Find shortest style element to minimize re-parse time in the general * case. + * + * We cache the lengths of the style sheets in order to avoid expensive + * calls to retrieve their actual contents. Note that if another module + * or script makes changes to the style sheets that we are unaware of, + * the worst that will happen is that we will choose a style sheet to + * append to that is not actually of minimum size. */ int shortestLen = Integer.MAX_VALUE; int shortestIdx = -1; - for (int i = 0; i < idx; i++) { - if (STYLE_ELEMENT_LENGTHS.get(i) < shortestLen) { - shortestLen = STYLE_ELEMENT_LENGTHS.get(i); + for (int i = 0; i < numStyles; i++) { + int len = styleSheetLengths[i]; + if (len == 0) { + // Cache the length + len = styleSheetLengths[i] = getDocumentStyleSheetLength(i); + } + if (len <= shortestLen) { + shortestLen = len; shortestIdx = i; } } - - /** - * This assertion can fail if the max number of style elements exist - * before this module can inject any style elements, so STYLE_ELEMENTS - * will be empty. However, the fix would degrade performance for the - * general case. TODO(jlabanca): Can we handle this scenario - * efficiently? - */ - assert shortestIdx != -1; - - StyleElement style = STYLE_ELEMENTS.get(shortestIdx); - STYLE_ELEMENT_LENGTHS.set(shortestIdx, shortestLen + contents.length()); - appendContents(style, contents); - return style; + styleSheetLengths[shortestIdx] += contents.length(); + return appendToStyleSheet(shortestIdx, contents, true); } } @Override public StyleElement injectStyleSheetAtEnd(String contents) { - if (STYLE_ELEMENTS.length() == 0) { - return injectStyleSheet(contents); + int documentStyleCount = getDocumentStyleCount(); + if (documentStyleCount == 0) { + return createNewStyleSheet(contents); } - - int idx = STYLE_ELEMENTS.length() - 1; - StyleElement style = STYLE_ELEMENTS.get(idx); - STYLE_ELEMENT_LENGTHS.set(idx, STYLE_ELEMENT_LENGTHS.get(idx) - + contents.length()); - appendContents(style, contents); - - return style; + + return appendToStyleSheet(documentStyleCount - 1, contents, true); } @Override public StyleElement injectStyleSheetAtStart(String contents) { - if (STYLE_ELEMENTS.length() == 0) { - return injectStyleSheet(contents); + if (getDocumentStyleCount() == 0) { + return createNewStyleSheet(contents); } - - StyleElement style = STYLE_ELEMENTS.get(0); - STYLE_ELEMENT_LENGTHS.set(0, STYLE_ELEMENT_LENGTHS.get(0) - + contents.length()); - prependContents(style, contents); - - return style; + + return appendToStyleSheet(0, contents, false); // prepend } public native void prependContents(StyleElement style, String contents) /*-{ style.cssText = contents + style.cssText; }-*/; - @Override - public native void setContents(StyleElement style, String contents) /*-{ - style.cssText = contents; - }-*/; + private StyleElement appendToStyleSheet(int idx, String contents, boolean append) { + StyleElement style = getDocumentStyleSheet(idx); + if (append) { + appendContents(style, contents); + } else { + prependContents(style, contents); + } + return style; + } private native StyleElement createElement() /*-{ return $doc.createStyleSheet(); }-*/; - private native int getDocumentStyleCount() /*-{ - return $doc.styleSheets.length; - }-*/; + private StyleElement createNewStyleSheet(String contents) { + StyleElement style = createElement(); + style.setCssText(contents); + return style; + } } private static final JsArrayString toInject = JavaScriptObject.createArray().cast();