JSCSSStyleDeclarationCustom.cpp revision cad810f21b803229eb11403f9209855525a25d57
1/* 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "JSCSSStyleDeclarationCustom.h" 28 29#include "CSSMutableStyleDeclaration.h" 30#include "CSSPrimitiveValue.h" 31#include "CSSValue.h" 32#include "PlatformString.h" 33#include <runtime/StringObjectThatMasqueradesAsUndefined.h> 34#include <runtime/StringPrototype.h> 35#include <wtf/ASCIICType.h> 36#include <wtf/text/AtomicString.h> 37 38using namespace JSC; 39using namespace WTF; 40 41namespace WebCore { 42 43void JSCSSStyleDeclaration::markChildren(MarkStack& markStack) 44{ 45 Base::markChildren(markStack); 46 47 CSSStyleDeclaration* declaration = impl(); 48 JSGlobalData& globalData = *Heap::heap(this)->globalData(); 49 50 if (CSSRule* parentRule = declaration->parentRule()) 51 markDOMObjectWrapper(markStack, globalData, parentRule); 52 53 if (declaration->isMutableStyleDeclaration()) { 54 CSSMutableStyleDeclaration* mutableDeclaration = static_cast<CSSMutableStyleDeclaration*>(declaration); 55 CSSMutableStyleDeclaration::const_iterator end = mutableDeclaration->end(); 56 for (CSSMutableStyleDeclaration::const_iterator it = mutableDeclaration->begin(); it != end; ++it) 57 markDOMObjectWrapper(markStack, globalData, it->value()); 58 } 59} 60 61// Check for a CSS prefix. 62// Passed prefix is all lowercase. 63// First character of the prefix within the property name may be upper or lowercase. 64// Other characters in the prefix within the property name must be lowercase. 65// The prefix within the property name must be followed by a capital letter. 66static bool hasCSSPropertyNamePrefix(const Identifier& propertyName, const char* prefix) 67{ 68#ifndef NDEBUG 69 ASSERT(*prefix); 70 for (const char* p = prefix; *p; ++p) 71 ASSERT(isASCIILower(*p)); 72 ASSERT(propertyName.length()); 73#endif 74 75 if (toASCIILower(propertyName.characters()[0]) != prefix[0]) 76 return false; 77 78 unsigned length = propertyName.length(); 79 for (unsigned i = 1; i < length; ++i) { 80 if (!prefix[i]) 81 return isASCIIUpper(propertyName.characters()[i]); 82 if (propertyName.characters()[i] != prefix[i]) 83 return false; 84 } 85 return false; 86} 87 88static String cssPropertyName(const Identifier& propertyName, bool* hadPixelOrPosPrefix = 0) 89{ 90 if (hadPixelOrPosPrefix) 91 *hadPixelOrPosPrefix = false; 92 93 unsigned length = propertyName.length(); 94 if (!length) 95 return String(); 96 97 Vector<UChar> name; 98 name.reserveInitialCapacity(length); 99 100 unsigned i = 0; 101 102 if (hasCSSPropertyNamePrefix(propertyName, "css")) 103 i += 3; 104 else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) { 105 i += 5; 106 if (hadPixelOrPosPrefix) 107 *hadPixelOrPosPrefix = true; 108 } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) { 109 i += 3; 110 if (hadPixelOrPosPrefix) 111 *hadPixelOrPosPrefix = true; 112 } else if (hasCSSPropertyNamePrefix(propertyName, "webkit") 113 || hasCSSPropertyNamePrefix(propertyName, "khtml") 114 || hasCSSPropertyNamePrefix(propertyName, "apple")) 115 name.append('-'); 116 else { 117 if (isASCIIUpper(propertyName.characters()[0])) 118 return String(); 119 } 120 121 name.append(toASCIILower(propertyName.characters()[i++])); 122 123 for (; i < length; ++i) { 124 UChar c = propertyName.characters()[i]; 125 if (!isASCIIUpper(c)) 126 name.append(c); 127 else { 128 name.append('-'); 129 name.append(toASCIILower(c)); 130 } 131 } 132 133 return String::adopt(name); 134} 135 136static bool isCSSPropertyName(const Identifier& propertyName) 137{ 138 return CSSStyleDeclaration::isPropertyName(cssPropertyName(propertyName)); 139} 140 141bool JSCSSStyleDeclaration::canGetItemsForName(ExecState*, CSSStyleDeclaration*, const Identifier& propertyName) 142{ 143 return isCSSPropertyName(propertyName); 144} 145 146// FIXME: You can get these properties, and set them (see putDelegate below), 147// but you should also be able to enumerate them. 148JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) 149{ 150 JSCSSStyleDeclaration* thisObj = static_cast<JSCSSStyleDeclaration*>(asObject(slotBase)); 151 152 // Set up pixelOrPos boolean to handle the fact that 153 // pixelTop returns "CSS Top" as number value in unit pixels 154 // posTop returns "CSS top" as number value in unit pixels _if_ its a 155 // positioned element. if it is not a positioned element, return 0 156 // from MSIE documentation FIXME: IMPLEMENT THAT (Dirk) 157 bool pixelOrPos; 158 String prop = cssPropertyName(propertyName, &pixelOrPos); 159 RefPtr<CSSValue> v = thisObj->impl()->getPropertyCSSValue(prop); 160 if (v) { 161 if (pixelOrPos && v->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) 162 return jsNumber(static_pointer_cast<CSSPrimitiveValue>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX)); 163 return jsStringOrNull(exec, v->cssText()); 164 } 165 166 // If the property is a shorthand property (such as "padding"), 167 // it can only be accessed using getPropertyValue. 168 169 // Make the SVG 'filter' attribute undetectable, to avoid confusion with the IE 'filter' attribute. 170 if (propertyName == "filter") 171 return StringObjectThatMasqueradesAsUndefined::create(exec, stringToUString(thisObj->impl()->getPropertyValue(prop))); 172 173 return jsString(exec, thisObj->impl()->getPropertyValue(prop)); 174} 175 176 177bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&) 178{ 179 if (!isCSSPropertyName(propertyName)) 180 return false; 181 182 bool pixelOrPos; 183 String prop = cssPropertyName(propertyName, &pixelOrPos); 184 String propValue = valueToStringWithNullCheck(exec, value); 185 if (pixelOrPos) 186 propValue += "px"; 187 ExceptionCode ec = 0; 188 impl()->setProperty(prop, propValue, ec); 189 setDOMException(exec, ec); 190 return true; 191} 192 193} // namespace WebCore 194