Skip to content

Commit 3b1fe17

Browse files
committed
WIP: getComputedStyleForced
This is a work-in-progress commit for considering how to implement getComputedStyle to determine font sizing on a document element in a reliable way. Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
1 parent c709154 commit 3b1fe17

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

src/browser.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,109 @@ var browser = (function (util, xhrproxies, ayepromise, theWindow) {
177177
return defer.promise;
178178
};
179179

180+
var documentsHaveSameStyleSheets = function (doc1, doc2) {
181+
var i, ownerNode1, ownerNode2;
182+
183+
if (doc1 === doc2) {
184+
return true;
185+
}
186+
187+
if (!doc1 || !doc2) {
188+
return false;
189+
}
190+
191+
// Do length check first to rule out obviously different styles
192+
if (doc1.styleSheets.length !== doc2.styleSheets.length) {
193+
return false;
194+
}
195+
196+
// We use DOM3 isEqualNode to compare stylesheet equality
197+
// Although we could walk the tree and compare the CSSRule instances,
198+
// it's a lot of code and execution time. Make the conservative
199+
// assumption that they are not the same style.
200+
if (!doc1.isEqualNode) {
201+
return false;
202+
}
203+
204+
for (i = 0; i < doc1.styleSheets.length; i++) {
205+
ownerNode1 = doc1.styleSheets[i].ownerNode;
206+
ownerNode2 = doc2.styleSheets[i].ownerNode;
207+
if (ownerNode1 && ownerNode2) {
208+
// Neither sheet was imported. Check node equality.
209+
if (!ownerNode1.isEqualNode(ownerNode2)) {
210+
return false;
211+
}
212+
} else if (ownerNode1 || ownerNode2) {
213+
// One of the sheets was @imported, the other was not
214+
return false;
215+
} else {
216+
// Both sheets were @imported. Equality of importing sheets
217+
// will determine overall equality.
218+
}
219+
}
220+
221+
return true;
222+
};
223+
224+
/** Wrapper for getComputedStyle which places the document in an iframe
225+
* if necessary to force calculation of computed styles. */
226+
module.getComputedStyleForced = function (element, pseudoElt) {
227+
var documentClone,
228+
iframe,
229+
style = theWindow.getComputedStyle(element, pseudoElt);
230+
231+
// For the style to be valid it must satisfy the following constraints:
232+
//
233+
// 1) It must not be null.
234+
// This can occur in Gecko when sizing is not possible.
235+
// https://bugzilla.mozilla.org/show_bug.cgi?id=795520#c7
236+
//
237+
// 2) It must not be an all-empty style declaration.
238+
// This can occur for detached elements in WebKit.
239+
// https://bugs.webkit.org/show_bug.cgi?id=14563
240+
//
241+
// We test for this using the display property, which is always
242+
// non-empty when computed.
243+
//
244+
// 3) It must be computed for the correct window (presentation shell)
245+
// Gecko will use the presentation shell of the window on which
246+
// getComputedStyle is called whenever the element does not have
247+
// an associated presentation shell (e.g. detached elements).
248+
//
249+
// We test for this by checking if the element has a defaultView.
250+
// If it does, it has a presentation shell. If it does not, then
251+
// we check if the style information in the element's document
252+
// differs from the style information in the window's document (they
253+
// will be the same if the document was cloned, in which case we can
254+
// avoid an unnecessary layout). If they differ, we do layout.
255+
if (style && style.display) {
256+
if (element.ownerDocument &&
257+
(element.ownerDocument.defaultView ||
258+
element.ownerDocument === theWindow.document ||
259+
documentsHaveSameStyleSheets(element.ownerDocument, theWindow.document))) {
260+
return style;
261+
}
262+
}
263+
264+
// FIXME: Should use proper dimensions.
265+
// Currently only used for properties not affected by page dimension.
266+
iframe = createHiddenSandboxedIFrame(theWindow.document, 300, 300);
267+
documentClone = iframe.contentDocument.importNode(
268+
element.ownerDocument.documentElement,
269+
true
270+
);
271+
iframe.contentDocument.replaceChild(
272+
documentClone,
273+
iframe.contentDocument.documentElement
274+
);
275+
// We need to add the element to the document so that its content gets loaded
276+
theWindow.document.body.appendChild(iframe);
277+
278+
// FIXME: Find cloned copy of element in documentClone...
279+
280+
return window.getComputedStyle(elementClone);
281+
};
282+
180283
var addHTMLTagAttributes = function (doc, html) {
181284
var attributeMatch = /<html((?:\s+[^>]*)?)>/im.exec(html),
182285
helperDoc = theWindow.document.implementation.createHTMLDocument(''),

0 commit comments

Comments
 (0)