Bug 1876542 - Unzoom resolved values in getComputedStyle. r=firefox-style-system-reviewers,zrhoffman

Extend the existing test to cover most other cases that can cause us to
return a length from getComputedStyle.

Differential Revision: https://phabricator.services.mozilla.com/D205225
This commit is contained in:
Emilio Cobos Álvarez 2024-03-22 17:20:12 +00:00
parent 2eb0304b97
commit f741262fe9
11 changed files with 138 additions and 141 deletions

View File

@ -1358,11 +1358,28 @@ already_AddRefed<nsROCSSPrimitiveValue> nsComputedDOMStyle::MatrixToCSSValue(
/* Create a value to hold our result. */
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetString(resultString);
return val.forget();
}
already_AddRefed<nsROCSSPrimitiveValue> nsComputedDOMStyle::AppUnitsToCSSValue(
nscoord aAppUnits) {
return PixelsToCSSValue(CSSPixel::FromAppUnits(aAppUnits));
}
already_AddRefed<nsROCSSPrimitiveValue> nsComputedDOMStyle::PixelsToCSSValue(
float aPixels) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToPixels(val, aPixels);
return val.forget();
}
void nsComputedDOMStyle::SetValueToPixels(nsROCSSPrimitiveValue* aValue,
float aPixels) {
MOZ_ASSERT(mComputedStyle);
aValue->SetPixels(mComputedStyle->EffectiveZoom().Unzoom(aPixels));
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetMozOsxFontSmoothing() {
if (nsContentUtils::ShouldResistFingerprinting(
mPresShell->GetPresContext()->GetDocShell(),
@ -1614,9 +1631,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
// Add any leading implicit tracks.
if (serializeImplicit) {
for (uint32_t i = 0; i < numLeadingImplicitTracks; ++i) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(trackSizes[i]);
valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(AppUnitsToCSSValue(trackSizes[i]));
}
}
@ -1652,8 +1667,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
for (uint32_t i = 0; i < repeatStart; i++) {
AppendGridLineNames(valueList, aTrackInfo.mResolvedLineNames[i]);
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(*trackSizeIter++);
valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(AppUnitsToCSSValue(*trackSizeIter++));
}
auto lineNameIter = aTrackInfo.mResolvedLineNames.cbegin() + repeatStart;
// Write the track names at the start of the repeat, including the names
@ -1666,9 +1680,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
// track).
const nscoord firstRepeatTrackSize =
(!aTrackInfo.mRemovedRepeatTracks[0]) ? *trackSizeIter++ : 0;
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(firstRepeatTrackSize);
valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(AppUnitsToCSSValue(firstRepeatTrackSize));
}
// Write the line names and track sizes inside the repeat, checking for
// removed tracks (size 0).
@ -1688,9 +1700,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
trackSizeIter != explicitTrackSizeEnd);
const nscoord repeatTrackSize =
(!aTrackInfo.mRemovedRepeatTracks[i]) ? *trackSizeIter++ : 0;
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(repeatTrackSize);
valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(AppUnitsToCSSValue(repeatTrackSize));
}
// The resolved line names include a single repetition of the auto-repeat
// line names. Skip over those.
@ -1698,9 +1708,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
// Write out any more tracks after the repeat.
while (trackSizeIter != explicitTrackSizeEnd) {
AppendGridLineNames(valueList, *lineNameIter++);
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(*trackSizeIter++);
valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(AppUnitsToCSSValue(*trackSizeIter++));
}
// Write the final trailing line name.
AppendGridLineNames(valueList, *lineNameIter++);
@ -1711,18 +1719,15 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetGridTemplateColumnsRows(
if (i == numExplicitTracks) {
break;
}
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(trackSizes[i + numLeadingImplicitTracks]);
valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(
AppUnitsToCSSValue(trackSizes[i + numLeadingImplicitTracks]));
}
}
// Add any trailing implicit tracks.
if (serializeImplicit) {
for (uint32_t i = numLeadingImplicitTracks + numExplicitTracks;
i < numSizes; ++i) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(trackSizes[i]);
valueList->AppendCSSValue(val.forget());
valueList->AppendCSSValue(AppUnitsToCSSValue(trackSizes[i]));
}
}
@ -1787,15 +1792,9 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetPaddingRight() {
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetBorderSpacing() {
RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
RefPtr<nsROCSSPrimitiveValue> xSpacing = new nsROCSSPrimitiveValue;
RefPtr<nsROCSSPrimitiveValue> ySpacing = new nsROCSSPrimitiveValue;
const nsStyleTableBorder* border = StyleTableBorder();
xSpacing->SetAppUnits(border->mBorderSpacingCol);
ySpacing->SetAppUnits(border->mBorderSpacingRow);
valueList->AppendCSSValue(xSpacing.forget());
valueList->AppendCSSValue(ySpacing.forget());
valueList->AppendCSSValue(AppUnitsToCSSValue(border->mBorderSpacingCol));
valueList->AppendCSSValue(AppUnitsToCSSValue(border->mBorderSpacingRow));
return valueList.forget();
}
@ -1833,32 +1832,26 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetMarginRight() {
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetHeight() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
if (mInnerFrame && !IsNonReplacedInline(mInnerFrame)) {
AssertFlushedPendingReflows();
nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
val->SetAppUnits(mInnerFrame->GetContentRect().height +
adjustedValues.TopBottom());
} else {
SetValueToSize(val, StylePosition()->mHeight);
const nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
return AppUnitsToCSSValue(mInnerFrame->GetContentRect().height +
adjustedValues.TopBottom());
}
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToSize(val, StylePosition()->mHeight);
return val.forget();
}
already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetWidth() {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
if (mInnerFrame && !IsNonReplacedInline(mInnerFrame)) {
AssertFlushedPendingReflows();
nsMargin adjustedValues = GetAdjustedValuesForBoxSizing();
val->SetAppUnits(mInnerFrame->GetContentRect().width +
adjustedValues.LeftRight());
} else {
SetValueToSize(val, StylePosition()->mWidth);
return AppUnitsToCSSValue(mInnerFrame->GetContentRect().width +
adjustedValues.LeftRight());
}
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToSize(val, StylePosition()->mWidth);
return val.forget();
}
@ -1968,14 +1961,13 @@ static_assert(eSideTop == 0 && eSideRight == 1 && eSideBottom == 2 &&
already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
mozilla::Side aSide, bool aResolveAuto, PercentageBaseGetter aWidthGetter,
PercentageBaseGetter aHeightGetter) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
const nsStylePosition* positionData = StylePosition();
int32_t sign = 1;
LengthPercentageOrAuto coord = positionData->mOffset.Get(aSide);
if (coord.IsAuto()) {
if (!aResolveAuto) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetString("auto");
return val.forget();
}
@ -1983,14 +1975,12 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
sign = -1;
}
if (!coord.IsLengthPercentage()) {
val->SetPixels(0.0f);
return val.forget();
return PixelsToCSSValue(0.0f);
}
auto& lp = coord.AsLengthPercentage();
const auto& lp = coord.AsLengthPercentage();
if (lp.ConvertsToLength()) {
val->SetPixels(sign * lp.ToLengthInCSSPixels());
return val.forget();
return PixelsToCSSValue(sign * lp.ToLengthInCSSPixels());
}
PercentageBaseGetter baseGetter = (aSide == eSideLeft || aSide == eSideRight)
@ -1998,12 +1988,10 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetNonStaticPositionOffset(
: aHeightGetter;
nscoord percentageBase;
if (!(this->*baseGetter)(percentageBase)) {
val->SetPixels(0.0f);
return val.forget();
return PixelsToCSSValue(0.0f);
}
nscoord result = lp.Resolve(percentageBase);
val->SetAppUnits(sign * result);
return val.forget();
return AppUnitsToCSSValue(sign * result);
}
already_AddRefed<CSSValue> nsComputedDOMStyle::GetAbsoluteOffset(
@ -2013,9 +2001,7 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetAbsoluteOffset(
const auto& oppositeCoord = offset.Get(NS_OPPOSITE_SIDE(aSide));
if (coord.IsAuto() || oppositeCoord.IsAuto()) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
val->SetAppUnits(GetUsedAbsoluteOffset(aSide));
return val.forget();
return AppUnitsToCSSValue(GetUsedAbsoluteOffset(aSide));
}
return GetNonStaticPositionOffset(
@ -2096,23 +2082,18 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetStaticOffset(
already_AddRefed<CSSValue> nsComputedDOMStyle::GetPaddingWidthFor(
mozilla::Side aSide) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
auto& padding = StylePadding()->mPadding.Get(aSide);
const auto& padding = StylePadding()->mPadding.Get(aSide);
if (!mInnerFrame || !PaddingNeedsUsedValue(padding, *mComputedStyle)) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToLengthPercentage(val, padding, true);
} else {
AssertFlushedPendingReflows();
val->SetAppUnits(mInnerFrame->GetUsedPadding().Side(aSide));
return val.forget();
}
return val.forget();
AssertFlushedPendingReflows();
return AppUnitsToCSSValue(mInnerFrame->GetUsedPadding().Side(aSide));
}
already_AddRefed<CSSValue> nsComputedDOMStyle::GetBorderWidthFor(
mozilla::Side aSide) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
nscoord width;
if (mInnerFrame && mComputedStyle->StyleDisplay()->HasAppearance()) {
AssertFlushedPendingReflows();
@ -2120,29 +2101,23 @@ already_AddRefed<CSSValue> nsComputedDOMStyle::GetBorderWidthFor(
} else {
width = StyleBorder()->GetComputedBorderWidth(aSide);
}
val->SetAppUnits(width);
return val.forget();
return AppUnitsToCSSValue(width);
}
already_AddRefed<CSSValue> nsComputedDOMStyle::GetMarginFor(Side aSide) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
auto& margin = StyleMargin()->mMargin.Get(aSide);
const auto& margin = StyleMargin()->mMargin.Get(aSide);
if (!mInnerFrame || margin.ConvertsToLength()) {
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
SetValueToLengthPercentageOrAuto(val, margin, false);
} else {
AssertFlushedPendingReflows();
// For tables, GetUsedMargin always returns an empty margin, so we
// should read the margin from the table wrapper frame instead.
val->SetAppUnits(mOuterFrame->GetUsedMargin().Side(aSide));
NS_ASSERTION(mOuterFrame == mInnerFrame ||
mInnerFrame->GetUsedMargin() == nsMargin(0, 0, 0, 0),
"Inner tables must have zero margins");
return val.forget();
}
return val.forget();
AssertFlushedPendingReflows();
// For tables, GetUsedMargin always returns an empty margin, so we
// should read the margin from the table wrapper frame instead.
NS_ASSERTION(
mOuterFrame == mInnerFrame || mInnerFrame->GetUsedMargin() == nsMargin(),
"Inner tables must have zero margins");
return AppUnitsToCSSValue(mOuterFrame->GetUsedMargin().Side(aSide));
}
static void SetValueToExtremumLength(nsROCSSPrimitiveValue* aValue,
@ -2223,7 +2198,7 @@ void nsComputedDOMStyle::SetValueToLengthPercentage(
if (aClampNegativeCalc) {
length = std::max(float(length), 0.0f);
}
return aValue->SetPixels(length);
return SetValueToPixels(aValue, length);
}
if (aLength.ConvertsToPercentage()) {
float result = aLength.ToPercentage();

View File

@ -148,6 +148,10 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
private:
already_AddRefed<nsROCSSPrimitiveValue> AppUnitsToCSSValue(nscoord);
already_AddRefed<nsROCSSPrimitiveValue> PixelsToCSSValue(float);
void SetValueToPixels(nsROCSSPrimitiveValue*, float);
void GetPropertyValue(const nsCSSPropertyID aPropID,
const nsACString& aMaybeCustomPropertyNme,
nsACString& aValue);

View File

@ -102,20 +102,12 @@ void nsROCSSPrimitiveValue::SetDegree(float aValue) {
mType = CSS_DEG;
}
void nsROCSSPrimitiveValue::SetAppUnits(nscoord aValue) {
SetPixels(nsPresContext::AppUnitsToFloatCSSPixels(aValue));
}
void nsROCSSPrimitiveValue::SetPixels(float aValue) {
Reset();
mValue.mFloat = aValue;
mType = CSS_PX;
}
void nsROCSSPrimitiveValue::SetAppUnits(float aValue) {
SetAppUnits(NSToCoordRound(aValue));
}
void nsROCSSPrimitiveValue::SetString(const nsACString& aString) {
Reset();
mValue.mString = ToNewUnicode(aString, mozilla::fallible);

View File

@ -48,8 +48,6 @@ class nsROCSSPrimitiveValue final : public mozilla::dom::CSSValue {
void SetPercent(float aValue);
void SetDegree(float aValue);
void SetPixels(float aValue);
void SetAppUnits(nscoord aValue);
void SetAppUnits(float aValue);
void SetString(const nsACString& aString);
void SetString(const nsAString& aString);

View File

@ -383,6 +383,15 @@ impl Zoom {
if self == Self::ONE {
return value;
}
self.value() * value
value * self.value()
}
/// Returns the un-zoomed value.
#[inline]
pub fn unzoom(self, value: f32) -> f32 {
if self == Self::ONE {
return value;
}
value / self.value()
}
}

View File

@ -1359,7 +1359,7 @@ impl ToResolvedValue for LineHeight {
context.style.get_font(),
wm,
Some(context.element_info.element),
))
).to_resolved_value(context))
}
#[inline]

View File

@ -12,6 +12,7 @@ use crate::values::generics::length::{
GenericLengthOrNumber, GenericLengthPercentageOrNormal, GenericMaxSize, GenericSize,
};
use crate::values::generics::NonNegative;
use crate::values::resolved::{Context as ResolvedContext, ToResolvedValue};
use crate::values::specified::length::{AbsoluteLength, FontBaseSize, LineHeightBase};
use crate::values::{specified, CSSFloat};
use crate::Zero;
@ -227,12 +228,24 @@ impl Size {
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToResolvedValue,
ToShmem,
)]
#[repr(C)]
pub struct CSSPixelLength(CSSFloat);
impl ToResolvedValue for CSSPixelLength {
type ResolvedValue = Self;
fn to_resolved_value(self, context: &ResolvedContext) -> Self::ResolvedValue {
Self(context.style.effective_zoom.unzoom(self.0))
}
#[inline]
fn from_resolved_value(value: Self::ResolvedValue) -> Self {
value
}
}
impl fmt::Debug for CSSPixelLength {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)?;

View File

@ -30,6 +30,7 @@ use crate::values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZer
use crate::values::distance::{ComputeSquaredDistance, SquaredDistance};
use crate::values::generics::calc::{CalcUnits, PositivePercentageBasis};
use crate::values::generics::{calc, NonNegative};
use crate::values::resolved::{Context as ResolvedContext, ToResolvedValue};
use crate::values::specified::length::{FontBaseSize, LineHeightBase};
use crate::values::{specified, CSSFloat};
use crate::{Zero, ZeroNoPercent};
@ -164,6 +165,25 @@ impl MallocSizeOf for LengthPercentage {
}
}
impl ToResolvedValue for LengthPercentage {
type ResolvedValue = Self;
fn to_resolved_value(self, context: &ResolvedContext) -> Self::ResolvedValue {
if context.style.effective_zoom.is_one() {
return self;
}
match self.unpack() {
Unpacked::Length(l) => Self::new_length(l.to_resolved_value(context)),
Unpacked::Percentage(..) | Unpacked::Calc(..) => self,
}
}
#[inline]
fn from_resolved_value(value: Self::ResolvedValue) -> Self {
value
}
}
/// An unpacked `<length-percentage>` that borrows the `calc()` variant.
#[derive(Clone, Debug, PartialEq, ToCss)]
enum Unpacked<'a> {

View File

@ -95,7 +95,6 @@ trivial_to_resolved_value!(computed::url::ComputedImageUrl);
trivial_to_resolved_value!(crate::Namespace);
#[cfg(feature = "servo")]
trivial_to_resolved_value!(crate::Prefix);
trivial_to_resolved_value!(computed::LengthPercentage);
trivial_to_resolved_value!(style_traits::values::specified::AllowedNumericType);
trivial_to_resolved_value!(computed::TimingFunction);

View File

@ -1,12 +0,0 @@
[computedStyle-zoom.html]
[getComputedStyle for elements with css zoom 2]
expected: FAIL
[getComputedStyle for elements with css zoom 3]
expected: FAIL
[getComputedStyle for elements with css zoom 4]
expected: FAIL
[getComputedStyle for elements with css zoom 5]
expected: FAIL

View File

@ -5,23 +5,23 @@
<link rel="help" href="https://drafts.csswg.org/css-viewport/">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<head>
<style>
div {
<style>
div {
width: 64px;
height: 64px;
line-height: 64px;
text-indent: 64px;
background-color: blue
}
div.x4_zoom {
}
div.x4_zoom {
zoom: 4.0;
background-color: blueviolet;
}
div.x2_zoom {
}
div.x2_zoom {
background-color: chartreuse;
zoom: 2.0;
}
</style>
}
</style>
</head>
<body>
<div id="no_zoom"></div>
@ -29,7 +29,7 @@
<div class="x2_zoom" id="parent_div">
<div class="x4_zoom" id="nested_zoom"></div>
</div>
<div class="x2_zoom" id="testing_set_style" style="height: 1px; width: 1px;"></div>
<div class="x2_zoom" id="testing_set_style" style="height: 1px; width: 1px; line-height: 1px; text-indent: 1px;"></div>
<script>
test(function() {
assert_true(!!no_zoom, "no zoom target exists");
@ -37,38 +37,37 @@
assert_true(!!nested_zoom, "zoom target exists");
assert_true(!!parent_div, "parent div with zoom exists")
});
function assert_length_props(style, expected) {
for (let prop of ["width", "height", "line-height", "text-indent"]) {
assert_equals(style.getPropertyValue(prop), expected, prop);
}
}
test(function(){
noZoomStyle = window.getComputedStyle(no_zoom);
assert_equals(noZoomStyle.getPropertyValue("width"), "64px");
assert_equals(noZoomStyle.getPropertyValue("height"), "64px");
let noZoomStyle = getComputedStyle(no_zoom);
assert_length_props(noZoomStyle, "64px");
assert_equals(noZoomStyle.getPropertyValue("zoom"), "1");
});
test(function(){
withZoomStyle = window.getComputedStyle(with_zoom);
assert_equals(withZoomStyle.getPropertyValue("width"), "64px");
assert_equals(withZoomStyle.getPropertyValue("height"), "64px");
let withZoomStyle = getComputedStyle(with_zoom);
assert_length_props(withZoomStyle, "64px");
assert_equals(withZoomStyle.getPropertyValue("zoom"), "4");
});
test(function(){
parentWithZoomStyle = window.getComputedStyle(parent_div);
assert_equals(parentWithZoomStyle.getPropertyValue("width"), "64px");
assert_equals(parentWithZoomStyle.getPropertyValue("height"), "64px");
let parentWithZoomStyle = getComputedStyle(parent_div);
assert_length_props(parentWithZoomStyle, "64px");
assert_equals(parentWithZoomStyle.getPropertyValue("zoom"), "2");
});
test(function(){
nestedZoomStyle = window.getComputedStyle(nested_zoom);
assert_equals(nestedZoomStyle.getPropertyValue("width"), "64px");
assert_equals(nestedZoomStyle.getPropertyValue("height"), "64px");
nestedZoomStyle = getComputedStyle(nested_zoom);
assert_length_props(nestedZoomStyle, "64px");
assert_equals(nestedZoomStyle.getPropertyValue("zoom"), "4");
});
test(function(){
testDivStyle = window.getComputedStyle(testing_set_style);
assert_equals(testDivStyle.getPropertyValue("width"), "1px");
assert_equals(testDivStyle.getPropertyValue("height"), "1px");
testDivStyle = getComputedStyle(testing_set_style);
assert_length_props(testDivStyle, "1px");
assert_equals(testDivStyle.getPropertyValue("zoom"), "2");
window.testing_set_style.setAttribute("style", "width: 64px; height: 64px;");
assert_equals(testDivStyle.getPropertyValue("width"), "64px");
assert_equals(testDivStyle.getPropertyValue("height"), "64px");
testing_set_style.setAttribute("style", "width: 64px; height: 64px; line-height: 64px; text-indent: 64px;");
assert_length_props(testDivStyle, "64px");
assert_equals(testDivStyle.getPropertyValue("zoom"), "2");
});
</script>