• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <wtf/text/StringBuilder.h>
38 #include <wtf/text/StringConcatenate.h>
39 
40 using namespace JSC;
41 using namespace WTF;
42 
43 namespace WebCore {
44 
markChildren(MarkStack & markStack)45 void JSCSSStyleDeclaration::markChildren(MarkStack& markStack)
46 {
47     Base::markChildren(markStack);
48 
49     CSSStyleDeclaration* declaration = impl();
50     JSGlobalData& globalData = *Heap::heap(this)->globalData();
51 
52     if (CSSRule* parentRule = declaration->parentRule())
53         markDOMObjectWrapper(markStack, globalData, parentRule);
54 
55     if (declaration->isMutableStyleDeclaration()) {
56         CSSMutableStyleDeclaration* mutableDeclaration = static_cast<CSSMutableStyleDeclaration*>(declaration);
57         CSSMutableStyleDeclaration::const_iterator end = mutableDeclaration->end();
58         for (CSSMutableStyleDeclaration::const_iterator it = mutableDeclaration->begin(); it != end; ++it)
59             markDOMObjectWrapper(markStack, globalData, it->value());
60     }
61 }
62 
63 // Check for a CSS prefix.
64 // Passed prefix is all lowercase.
65 // First character of the prefix within the property name may be upper or lowercase.
66 // Other characters in the prefix within the property name must be lowercase.
67 // The prefix within the property name must be followed by a capital letter.
hasCSSPropertyNamePrefix(const Identifier & propertyName,const char * prefix)68 static bool hasCSSPropertyNamePrefix(const Identifier& propertyName, const char* prefix)
69 {
70 #ifndef NDEBUG
71     ASSERT(*prefix);
72     for (const char* p = prefix; *p; ++p)
73         ASSERT(isASCIILower(*p));
74     ASSERT(propertyName.length());
75 #endif
76 
77     if (toASCIILower(propertyName.characters()[0]) != prefix[0])
78         return false;
79 
80     unsigned length = propertyName.length();
81     for (unsigned i = 1; i < length; ++i) {
82         if (!prefix[i])
83             return isASCIIUpper(propertyName.characters()[i]);
84         if (propertyName.characters()[i] != prefix[i])
85             return false;
86     }
87     return false;
88 }
89 
cssPropertyName(const Identifier & propertyName,bool * hadPixelOrPosPrefix=0)90 static String cssPropertyName(const Identifier& propertyName, bool* hadPixelOrPosPrefix = 0)
91 {
92     if (hadPixelOrPosPrefix)
93         *hadPixelOrPosPrefix = false;
94 
95     unsigned length = propertyName.length();
96     if (!length)
97         return String();
98 
99     StringBuilder builder;
100     builder.reserveCapacity(length);
101 
102     unsigned i = 0;
103 
104     if (hasCSSPropertyNamePrefix(propertyName, "css"))
105         i += 3;
106     else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) {
107         i += 5;
108         if (hadPixelOrPosPrefix)
109             *hadPixelOrPosPrefix = true;
110     } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) {
111         i += 3;
112         if (hadPixelOrPosPrefix)
113             *hadPixelOrPosPrefix = true;
114     } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")
115             || hasCSSPropertyNamePrefix(propertyName, "khtml")
116             || hasCSSPropertyNamePrefix(propertyName, "apple"))
117         builder.append('-');
118     else {
119         if (isASCIIUpper(propertyName.characters()[0]))
120             return String();
121     }
122 
123     builder.append(toASCIILower(propertyName.characters()[i++]));
124 
125     for (; i < length; ++i) {
126         UChar c = propertyName.characters()[i];
127         if (!isASCIIUpper(c))
128             builder.append(c);
129         else
130             builder.append(makeString('-', toASCIILower(c)));
131     }
132 
133     return builder.toString();
134 }
135 
isCSSPropertyName(const Identifier & propertyIdentifier)136 static bool isCSSPropertyName(const Identifier& propertyIdentifier)
137 {
138     // FIXME: This mallocs a string for the property name and then throws it
139     // away.  This shows up on peacekeeper's domDynamicCreationCreateElement.
140     return CSSStyleDeclaration::isPropertyName(cssPropertyName(propertyIdentifier));
141 }
142 
canGetItemsForName(ExecState *,CSSStyleDeclaration *,const Identifier & propertyName)143 bool JSCSSStyleDeclaration::canGetItemsForName(ExecState*, CSSStyleDeclaration*, const Identifier& propertyName)
144 {
145     return isCSSPropertyName(propertyName);
146 }
147 
148 // FIXME: You can get these properties, and set them (see putDelegate below),
149 // but you should also be able to enumerate them.
nameGetter(ExecState * exec,JSValue slotBase,const Identifier & propertyName)150 JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
151 {
152     JSCSSStyleDeclaration* thisObj = static_cast<JSCSSStyleDeclaration*>(asObject(slotBase));
153 
154     // Set up pixelOrPos boolean to handle the fact that
155     // pixelTop returns "CSS Top" as number value in unit pixels
156     // posTop returns "CSS top" as number value in unit pixels _if_ its a
157     // positioned element. if it is not a positioned element, return 0
158     // from MSIE documentation FIXME: IMPLEMENT THAT (Dirk)
159     bool pixelOrPos;
160     String prop = cssPropertyName(propertyName, &pixelOrPos);
161     RefPtr<CSSValue> v = thisObj->impl()->getPropertyCSSValue(prop);
162     if (v) {
163         if (pixelOrPos && v->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE)
164             return jsNumber(static_pointer_cast<CSSPrimitiveValue>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX));
165         return jsStringOrNull(exec, v->cssText());
166     }
167 
168     // If the property is a shorthand property (such as "padding"),
169     // it can only be accessed using getPropertyValue.
170 
171     // Make the SVG 'filter' attribute undetectable, to avoid confusion with the IE 'filter' attribute.
172     if (propertyName == "filter")
173         return StringObjectThatMasqueradesAsUndefined::create(exec, stringToUString(thisObj->impl()->getPropertyValue(prop)));
174 
175     return jsString(exec, thisObj->impl()->getPropertyValue(prop));
176 }
177 
178 
putDelegate(ExecState * exec,const Identifier & propertyName,JSValue value,PutPropertySlot &)179 bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&)
180 {
181     bool pixelOrPos;
182     String prop = cssPropertyName(propertyName, &pixelOrPos);
183     if (!CSSStyleDeclaration::isPropertyName(prop))
184         return false;
185 
186     String propValue = valueToStringWithNullCheck(exec, value);
187     if (pixelOrPos)
188         propValue += "px";
189     ExceptionCode ec = 0;
190     impl()->setProperty(prop, propValue, ec);
191     setDOMException(exec, ec);
192     return true;
193 }
194 
195 } // namespace WebCore
196