diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e87dec424b0..ef22ff24806 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -14,6 +14,9 @@ of the various WebClient properties should be clear in every case. This results in some minor changes the might have some impact for the backward compatibility. + + Properties ownerNode and href moved from CSSStyleSheet to StyleSheet. + Upgrade Apache commons-io to 2.15.0. diff --git a/src/main/java/org/htmlunit/javascript/host/css/CSSStyleSheet.java b/src/main/java/org/htmlunit/javascript/host/css/CSSStyleSheet.java index cb1d58c5da8..4309c257693 100644 --- a/src/main/java/org/htmlunit/javascript/host/css/CSSStyleSheet.java +++ b/src/main/java/org/htmlunit/javascript/host/css/CSSStyleSheet.java @@ -15,7 +15,6 @@ package org.htmlunit.javascript.host.css; import static org.htmlunit.BrowserVersionFeatures.STYLESHEET_ADD_RULE_RETURNS_POS; -import static org.htmlunit.BrowserVersionFeatures.STYLESHEET_HREF_EMPTY_IS_NULL; import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME; import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE; import static org.htmlunit.javascript.configuration.SupportedBrowser.FF; @@ -24,11 +23,8 @@ import java.io.IOException; import java.io.StringReader; -import java.net.MalformedURLException; -import java.net.URL; import java.util.ArrayList; import java.util.List; -import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -42,9 +38,6 @@ import org.htmlunit.cssparser.parser.InputSource; import org.htmlunit.cssparser.parser.selector.SelectorList; import org.htmlunit.html.DomNode; -import org.htmlunit.html.HtmlLink; -import org.htmlunit.html.HtmlPage; -import org.htmlunit.html.HtmlStyle; import org.htmlunit.javascript.configuration.JsxClass; import org.htmlunit.javascript.configuration.JsxConstructor; import org.htmlunit.javascript.configuration.JsxFunction; @@ -71,15 +64,9 @@ public class CSSStyleSheet extends StyleSheet { private static final Log LOG = LogFactory.getLog(CSSStyleSheet.class); - private static final Pattern NTH_NUMERIC = Pattern.compile("\\d+"); - private static final Pattern NTH_COMPLEX = Pattern.compile("[+-]?\\d*n\\w*([+-]\\w\\d*)?"); - /** The parsed stylesheet which this host object wraps. */ private final CssStyleSheet styleSheet_; - /** The HTML element which owns this stylesheet. */ - private final HTMLElement ownerNode_; - /** The collection of rules defined in this style sheet. */ private CSSRuleList cssRules_; private List cssRulesIndexFix_; @@ -89,8 +76,8 @@ public class CSSStyleSheet extends StyleSheet { */ @JsxConstructor({CHROME, EDGE, FF, FF_ESR}) public CSSStyleSheet() { + super(null); styleSheet_ = new CssStyleSheet(null, (InputSource) null, null); - ownerNode_ = null; } /** @@ -100,11 +87,12 @@ public CSSStyleSheet() { * @param uri this stylesheet's URI (used to resolved contained @import rules) */ public CSSStyleSheet(final HTMLElement element, final InputSource source, final String uri) { + super(element); + setParentScope(element.getWindow()); setPrototype(getPrototype(CSSStyleSheet.class)); styleSheet_ = new CssStyleSheet(element.getDomNodeOrDie(), source, uri); - ownerNode_ = element; } /** @@ -114,6 +102,8 @@ public CSSStyleSheet(final HTMLElement element, final InputSource source, final * @param uri this stylesheet's URI (used to resolved contained @import rules) */ public CSSStyleSheet(final HTMLElement element, final String styleSheet, final String uri) { + super(element); + final Window win = element.getWindow(); CssStyleSheet css = null; @@ -128,7 +118,6 @@ public CSSStyleSheet(final HTMLElement element, final String styleSheet, final S setPrototype(getPrototype(CSSStyleSheet.class)); styleSheet_ = css; - ownerNode_ = element; } /** @@ -139,10 +128,11 @@ public CSSStyleSheet(final HTMLElement element, final String styleSheet, final S */ public CSSStyleSheet(final HTMLElement element, final Scriptable parentScope, final CssStyleSheet cssStyleSheet) { + super(element); + setParentScope(parentScope); setPrototype(getPrototype(CSSStyleSheet.class)); styleSheet_ = cssStyleSheet; - ownerNode_ = element; } /** @@ -158,8 +148,9 @@ public CssStyleSheet getCssStyleSheet() { * @return the owner node */ @JsxGetter(IE) + @Override public HTMLElement getOwnerNode() { - return ownerNode_; + return super.getOwnerNode(); } /** @@ -168,7 +159,7 @@ public HTMLElement getOwnerNode() { */ @JsxGetter(IE) public HTMLElement getOwningElement() { - return ownerNode_; + return getOwnerNode(); } /** @@ -191,37 +182,12 @@ public CSSRuleList getCssRules() { } /** - * Returns the URL of the stylesheet. - * @return the URL of the stylesheet + * {@inheritDoc} */ @JsxGetter(IE) + @Override public String getHref() { - if (ownerNode_ != null) { - final DomNode node = ownerNode_.getDomNodeOrDie(); - if (node instanceof HtmlStyle) { - return null; - } - if (node instanceof HtmlLink) { - // - final HtmlLink link = (HtmlLink) node; - final String href = link.getHrefAttribute(); - if ("".equals(href) && getBrowserVersion().hasFeature(STYLESHEET_HREF_EMPTY_IS_NULL)) { - return null; - } - // Expand relative URLs. - try { - final HtmlPage page = (HtmlPage) link.getPage(); - final URL url = page.getFullyQualifiedUrl(href); - return url.toExternalForm(); - } - catch (final MalformedURLException e) { - // Log the error and fall through to the return values below. - LOG.warn(e.getMessage(), e); - } - } - } - - return getUri(); + return super.getHref(); } /** @@ -371,6 +337,7 @@ public void removeRule(final int position) { * For inline styles this is the page uri. * @return this stylesheet's URI (used to resolved contained @import rules) */ + @Override public String getUri() { return getCssStyleSheet().getUri(); } diff --git a/src/main/java/org/htmlunit/javascript/host/css/StyleSheet.java b/src/main/java/org/htmlunit/javascript/host/css/StyleSheet.java index 5e7a4d1e4fb..bae504b4ded 100644 --- a/src/main/java/org/htmlunit/javascript/host/css/StyleSheet.java +++ b/src/main/java/org/htmlunit/javascript/host/css/StyleSheet.java @@ -14,14 +14,26 @@ */ package org.htmlunit.javascript.host.css; +import static org.htmlunit.BrowserVersionFeatures.STYLESHEET_HREF_EMPTY_IS_NULL; import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME; import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE; import static org.htmlunit.javascript.configuration.SupportedBrowser.FF; import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR; +import java.net.MalformedURLException; +import java.net.URL; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.htmlunit.html.DomNode; +import org.htmlunit.html.HtmlLink; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlStyle; import org.htmlunit.javascript.HtmlUnitScriptable; import org.htmlunit.javascript.configuration.JsxClass; import org.htmlunit.javascript.configuration.JsxConstructor; +import org.htmlunit.javascript.configuration.JsxGetter; +import org.htmlunit.javascript.host.html.HTMLElement; /** * A JavaScript object for {@code StyleSheet}. @@ -32,10 +44,72 @@ @JsxClass public class StyleSheet extends HtmlUnitScriptable { + private static final Log LOG = LogFactory.getLog(StyleSheet.class); + + /** The HTML element which owns this stylesheet. */ + private final HTMLElement ownerNode_; + /** * Default constructor. */ @JsxConstructor({CHROME, EDGE, FF, FF_ESR}) public StyleSheet() { + ownerNode_ = null; + } + + public StyleSheet(final HTMLElement ownerNode) { + ownerNode_ = ownerNode; + } + + /** + * Returns the owner node. + * @return the owner node + */ + @JsxGetter + public HTMLElement getOwnerNode() { + return ownerNode_; + } + + /** + * Returns the URL of the stylesheet. + * @return the URL of the stylesheet + */ + @JsxGetter + public String getHref() { + if (ownerNode_ != null) { + final DomNode node = ownerNode_.getDomNodeOrDie(); + if (node instanceof HtmlStyle) { + return null; + } + if (node instanceof HtmlLink) { + // + final HtmlLink link = (HtmlLink) node; + final String href = link.getHrefAttribute(); + if ("".equals(href) && getBrowserVersion().hasFeature(STYLESHEET_HREF_EMPTY_IS_NULL)) { + return null; + } + // Expand relative URLs. + try { + final HtmlPage page = (HtmlPage) link.getPage(); + final URL url = page.getFullyQualifiedUrl(href); + return url.toExternalForm(); + } + catch (final MalformedURLException e) { + // Log the error and fall through to the return values below. + LOG.warn(e.getMessage(), e); + } + } + } + + return getUri(); + } + + /** + * Returns this stylesheet's URI (used to resolved contained @import rules). + * For inline styles this is the page uri. + * @return this stylesheet's URI (used to resolved contained @import rules) + */ + public String getUri() { + return null; } } diff --git a/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java b/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java index a3a0d2afd20..0cd124012c4 100644 --- a/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java +++ b/src/test/java/org/htmlunit/general/ElementOwnPropertiesTest.java @@ -148,6 +148,9 @@ private void testString(final String preparation, final String string) throws Ex + " @font-face { font-family: Delicious; src: url('Delicious-Bold.otf'); };\n" + " \n" + " \n" + + " \n" @@ -18572,6 +18575,24 @@ public void cssFontFaceRule() throws Exception { testString("", "document.styleSheets[2].cssRules[0]"); } + /** + * Test CSSImportRule. + * + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "constructor(),href[GCE],layerName[GCE],media[GSCE],styleSheet[GCE]", + FF = "constructor(),href[GCE],layerName[GCE],media[GSCE],styleSheet[GCE],supportsText[GCE]", + FF_ESR = "constructor(),href[GCE],layerName[GCE],media[GSCE],styleSheet[GCE],supportsText[GCE]", + IE = "constructor[],href[GCE],media[GCE],styleSheet[GCE]") + @HtmlUnitNYI(CHROME = "constructor(),href[GCE],media[GCE],styleSheet[GCE]", + EDGE = "constructor(),href[GCE],media[GCE],styleSheet[GCE]", + FF = "constructor(),href[GCE],media[GCE],styleSheet[GCE]", + FF_ESR = "constructor(),href[GCE],media[GCE],styleSheet[GCE]") + public void cssImportRule() throws Exception { + testString("", "document.styleSheets[3].cssRules[0]"); + } + /** * Test CSSRule. * @@ -18588,6 +18609,6 @@ public void cssFontFaceRule() throws Exception { FF = "constructor(),selectorText[GSCE],style[GCE]", FF_ESR = "constructor(),selectorText[GSCE],style[GCE]") public void cssStyleRule() throws Exception { - testString("", "document.styleSheets[3].cssRules[0]"); + testString("", "document.styleSheets[4].cssRules[0]"); } } diff --git a/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java b/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java index 42cc3bacc76..495387a52fd 100644 --- a/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java +++ b/src/test/java/org/htmlunit/general/ElementOwnPropertySymbolsTest.java @@ -141,6 +141,9 @@ private void testString(final String preparation, final String string) throws Ex + " @font-face { font-family: Delicious; src: url('Delicious-Bold.otf'); };\n" + " \n" + " \n" + + " \n" @@ -3851,6 +3854,18 @@ public void cssFontFaceRule() throws Exception { testString("", "document.styleSheets[2].cssRules[0]"); } + /** + * Test CSSImportRule. + * + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "Symbol(Symbol.toStringTag) [CSSImportRule]", + IE = "exception") + public void cssImportRule() throws Exception { + testString("", "document.styleSheets[3].cssRules[0]"); + } + /** * Test CSSRule. * @@ -3860,6 +3875,6 @@ public void cssFontFaceRule() throws Exception { @Alerts(DEFAULT = "Symbol(Symbol.toStringTag) [CSSStyleRule]", IE = "exception") public void cssStyleRule() throws Exception { - testString("", "document.styleSheets[3].cssRules[0]"); + testString("", "document.styleSheets[4].cssRules[0]"); } } diff --git a/src/test/java/org/htmlunit/general/ElementPropertiesTest.java b/src/test/java/org/htmlunit/general/ElementPropertiesTest.java index fd05eb10a93..d9005da2c98 100644 --- a/src/test/java/org/htmlunit/general/ElementPropertiesTest.java +++ b/src/test/java/org/htmlunit/general/ElementPropertiesTest.java @@ -148,6 +148,9 @@ private void testString(final String preparation, final String string) throws Ex + " @font-face { font-family: Delicious; src: url('Delicious-Bold.otf'); };\n" + " \n" + " \n" + + " \n" @@ -9474,10 +9477,10 @@ public void webKitMutationObserver() throws Exception { + "ownerRule,parentStyleSheet,removeRule(),replace(),replaceSync(),rules,title,type", IE = "addRule(),cssRules,deleteRule(),href,insertRule(),ownerNode," + "owningElement,removeRule(),rules") - @HtmlUnitNYI(CHROME = "addRule(),cssRules,deleteRule(),insertRule(),removeRule(),rules", - EDGE = "addRule(),cssRules,deleteRule(),insertRule(),removeRule(),rules", - FF = "addRule(),cssRules,deleteRule(),insertRule(),removeRule(),rules", - FF_ESR = "addRule(),cssRules,deleteRule(),insertRule(),removeRule(),rules") + @HtmlUnitNYI(CHROME = "addRule(),cssRules,deleteRule(),href,insertRule(),ownerNode,removeRule(),rules", + EDGE = "addRule(),cssRules,deleteRule(),href,insertRule(),ownerNode,removeRule(),rules", + FF = "addRule(),cssRules,deleteRule(),href,insertRule(),ownerNode,removeRule(),rules", + FF_ESR = "addRule(),cssRules,deleteRule(),href,insertRule(),ownerNode,removeRule(),rules") public void cssStyleSheet() throws Exception { testString("", "document.styleSheets[0]"); } @@ -9542,6 +9545,40 @@ public void cssFontFaceRule() throws Exception { testString("", "document.styleSheets[2].cssRules[0]"); } + /** + * Test CSSImportRule. + * + * @throws Exception if the test fails + */ + @Test + @Alerts(DEFAULT = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE,href," + + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,layerName,media,MEDIA_RULE,NAMESPACE_RULE," + + "PAGE_RULE,parentRule,parentStyleSheet,STYLE_RULE,styleSheet,SUPPORTS_RULE,type", + FF = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE,href," + + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,layerName,media,MEDIA_RULE,NAMESPACE_RULE," + + "PAGE_RULE,parentRule,parentStyleSheet,STYLE_RULE,styleSheet,SUPPORTS_RULE,supportsText,type", + FF_ESR = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE,href," + + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,layerName,media,MEDIA_RULE,NAMESPACE_RULE," + + "PAGE_RULE,parentRule,parentStyleSheet,STYLE_RULE,styleSheet,SUPPORTS_RULE,supportsText,type", + IE = "CHARSET_RULE,cssText,FONT_FACE_RULE,href,IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,media," + + "MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,STYLE_RULE,styleSheet,type," + + "UNKNOWN_RULE,VIEWPORT_RULE") + @HtmlUnitNYI(CHROME = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE,href," + + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,media,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE," + + "parentRule,parentStyleSheet,STYLE_RULE,styleSheet,SUPPORTS_RULE,type", + EDGE = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE,href," + + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,media,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE," + + "parentRule,parentStyleSheet,STYLE_RULE,styleSheet,SUPPORTS_RULE,type", + FF = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE,href," + + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,media,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE," + + "parentRule,parentStyleSheet,STYLE_RULE,styleSheet,SUPPORTS_RULE,type", + FF_ESR = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE,href," + + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,media,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE," + + "parentRule,parentStyleSheet,STYLE_RULE,styleSheet,SUPPORTS_RULE,type") + public void cssImportRule() throws Exception { + testString("", "document.styleSheets[3].cssRules[0]"); + } + /** * Test CSSRule. * @@ -9552,13 +9589,13 @@ public void cssFontFaceRule() throws Exception { + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,insertRule(),KEYFRAME_RULE,KEYFRAMES_RULE," + "MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText," + "style,STYLE_RULE,styleMap,SUPPORTS_RULE,type", - FF = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE," + FF = "CHARSET_RULE,COUNTER_STYLE_RULE,cssRules,cssText,deleteRule(),FONT_FACE_RULE," + + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,insertRule(),KEYFRAME_RULE,KEYFRAMES_RULE," + + "MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText," + + "style,STYLE_RULE,SUPPORTS_RULE,type", + FF_ESR = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE," + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE,parentRule," + "parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE,type", - FF_ESR = "CHARSET_RULE,COUNTER_STYLE_RULE,cssRules,cssText,deleteRule(),FONT_FACE_RULE," - + "FONT_FEATURE_VALUES_RULE,IMPORT_RULE,insertRule(),KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," - + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,selectorText,style," - + "STYLE_RULE,SUPPORTS_RULE,type", IE = "CHARSET_RULE,cssText,FONT_FACE_RULE,IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE," + "NAMESPACE_RULE,PAGE_RULE,parentRule,parentStyleSheet,readOnly,selectorText,style," + "STYLE_RULE,type,UNKNOWN_RULE,VIEWPORT_RULE") @@ -9568,10 +9605,10 @@ public void cssFontFaceRule() throws Exception { EDGE = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE," + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE,parentRule," + "parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE,type", - FF_ESR = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE," + FF = "CHARSET_RULE,COUNTER_STYLE_RULE,cssText,FONT_FACE_RULE,FONT_FEATURE_VALUES_RULE," + "IMPORT_RULE,KEYFRAME_RULE,KEYFRAMES_RULE,MEDIA_RULE,NAMESPACE_RULE,PAGE_RULE,parentRule," + "parentStyleSheet,selectorText,style,STYLE_RULE,SUPPORTS_RULE,type") public void cssStyleRule() throws Exception { - testString("", "document.styleSheets[3].cssRules[0]"); + testString("", "document.styleSheets[4].cssRules[0]"); } }