OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007-2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2007-2011 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #include "wtf/StdLibExtras.h" | 47 #include "wtf/StdLibExtras.h" |
48 #include "wtf/Vector.h" | 48 #include "wtf/Vector.h" |
49 #include "wtf/text/StringBuilder.h" | 49 #include "wtf/text/StringBuilder.h" |
50 #include "wtf/text/StringConcatenate.h" | 50 #include "wtf/text/StringConcatenate.h" |
51 | 51 |
52 using namespace WTF; | 52 using namespace WTF; |
53 using namespace std; | 53 using namespace std; |
54 | 54 |
55 namespace WebCore { | 55 namespace WebCore { |
56 | 56 |
57 // FIXME: Next two functions look lifted verbatim from JSCSSStyleDeclarationCust
om. Please remove duplication. | |
58 | 57 |
59 // Check for a CSS prefix. | |
60 // Passed prefix is all lowercase. | |
61 // First character of the prefix within the property name may be upper or lowerc
ase. | |
62 // Other characters in the prefix within the property name must be lowercase. | |
63 // The prefix within the property name must be followed by a capital letter. | |
64 static bool hasCSSPropertyNamePrefix(const String& propertyName, const char* pre
fix) | |
65 { | |
66 #ifndef NDEBUG | |
67 ASSERT(*prefix); | |
68 for (const char* p = prefix; *p; ++p) | |
69 ASSERT(isASCIILower(*p)); | |
70 ASSERT(propertyName.length()); | |
71 #endif | |
72 | |
73 if (toASCIILower(propertyName[0]) != prefix[0]) | |
74 return false; | |
75 | |
76 unsigned length = propertyName.length(); | |
77 for (unsigned i = 1; i < length; ++i) { | |
78 if (!prefix[i]) | |
79 return isASCIIUpper(propertyName[i]); | |
80 if (propertyName[i] != prefix[i]) | |
81 return false; | |
82 } | |
83 return false; | |
84 } | |
85 | |
86 class CSSPropertyInfo { | |
87 public: | |
88 CSSPropertyID propID; | |
89 bool hadPixelOrPosPrefix; | |
90 }; | |
91 | |
92 // When getting properties on CSSStyleDeclarations, the name used from | |
93 // Javascript and the actual name of the property are not the same, so | |
94 // we have to do the following translation. The translation turns upper | |
95 // case characters into lower case characters and inserts dashes to | |
96 // separate words. | |
97 // | |
98 // Example: 'backgroundPositionY' -> 'background-position-y' | |
99 // | |
100 // Also, certain prefixes such as 'pos', 'css-' and 'pixel-' are stripped | |
101 // and the hadPixelOrPosPrefix out parameter is used to indicate whether or | |
102 // not the property name was prefixed with 'pos-' or 'pixel-'. | |
103 static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String> v8PropertyName) | |
104 { | |
105 String propertyName = toWebCoreString(v8PropertyName); | |
106 typedef HashMap<String, CSSPropertyInfo*> CSSPropertyInfoMap; | |
107 DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ()); | |
108 CSSPropertyInfo* propInfo = map.get(propertyName); | |
109 if (!propInfo) { | |
110 unsigned length = propertyName.length(); | |
111 bool hadPixelOrPosPrefix = false; | |
112 if (!length) | |
113 return 0; | |
114 | |
115 StringBuilder builder; | |
116 builder.reserveCapacity(length); | |
117 | |
118 unsigned i = 0; | |
119 | |
120 if (hasCSSPropertyNamePrefix(propertyName, "css")) | |
121 i += 3; | |
122 else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) { | |
123 i += 5; | |
124 hadPixelOrPosPrefix = true; | |
125 } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) { | |
126 i += 3; | |
127 hadPixelOrPosPrefix = true; | |
128 } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")) | |
129 builder.append('-'); | |
130 else if (isASCIIUpper(propertyName[0])) | |
131 return 0; | |
132 | |
133 builder.append(toASCIILower(propertyName[i++])); | |
134 | |
135 for (; i < length; ++i) { | |
136 UChar c = propertyName[i]; | |
137 if (!isASCIIUpper(c)) | |
138 builder.append(c); | |
139 else { | |
140 builder.append('-'); | |
141 builder.append(toASCIILower(c)); | |
142 } | |
143 } | |
144 | |
145 String propName = builder.toString(); | |
146 CSSPropertyID propertyID = cssPropertyID(propName); | |
147 if (propertyID && RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID)) { | |
148 propInfo = new CSSPropertyInfo(); | |
149 propInfo->hadPixelOrPosPrefix = hadPixelOrPosPrefix; | |
150 propInfo->propID = propertyID; | |
151 map.add(propertyName, propInfo); | |
152 } | |
153 } | |
154 return propInfo; | |
155 } | |
156 | 58 |
157 v8::Handle<v8::Array> V8CSSStyleDeclaration::namedPropertyEnumerator(const v8::A
ccessorInfo& info) | 59 v8::Handle<v8::Array> V8CSSStyleDeclaration::namedPropertyEnumerator(const v8::A
ccessorInfo& info) |
158 { | 60 { |
159 typedef Vector<String, numCSSProperties - 1> PreAllocatedPropertyVector; | 61 typedef Vector<String, numCSSProperties - 1> PreAllocatedPropertyVector; |
160 DEFINE_STATIC_LOCAL(PreAllocatedPropertyVector, propertyNames, ()); | 62 DEFINE_STATIC_LOCAL(PreAllocatedPropertyVector, propertyNames, ()); |
161 static unsigned propertyNamesLength = 0; | 63 static unsigned propertyNamesLength = 0; |
162 | 64 |
163 if (propertyNames.isEmpty()) { | 65 if (propertyNames.isEmpty()) { |
164 for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { | 66 for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { |
165 CSSPropertyID propertyId = static_cast<CSSPropertyID>(id); | 67 CSSPropertyID propertyId = static_cast<CSSPropertyID>(id); |
(...skipping 11 matching lines...) Expand all Loading... |
177 properties->Set(v8Integer(i, info.GetIsolate()), v8String(key, info.GetI
solate())); | 79 properties->Set(v8Integer(i, info.GetIsolate()), v8String(key, info.GetI
solate())); |
178 } | 80 } |
179 | 81 |
180 return properties; | 82 return properties; |
181 } | 83 } |
182 | 84 |
183 v8::Handle<v8::Integer> V8CSSStyleDeclaration::namedPropertyQuery(v8::Local<v8::
String> v8Name, const v8::AccessorInfo& info) | 85 v8::Handle<v8::Integer> V8CSSStyleDeclaration::namedPropertyQuery(v8::Local<v8::
String> v8Name, const v8::AccessorInfo& info) |
184 { | 86 { |
185 // NOTE: cssPropertyInfo lookups incur several mallocs. | 87 // NOTE: cssPropertyInfo lookups incur several mallocs. |
186 // Successful lookups have the same cost the first time, but are cached. | 88 // Successful lookups have the same cost the first time, but are cached. |
187 if (cssPropertyInfo(v8Name)) | 89 String propertyName = toWebCoreString(v8Name); |
| 90 if (CSSStyleDeclaration::cssPropertyInfo(propertyName)) |
188 return v8Integer(0, info.GetIsolate()); | 91 return v8Integer(0, info.GetIsolate()); |
189 | 92 |
190 return v8::Handle<v8::Integer>(); | 93 return v8::Handle<v8::Integer>(); |
191 } | 94 } |
192 | 95 |
193 v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertyGetter(v8::Local<v8::S
tring> name, const v8::AccessorInfo& info) | 96 v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertySetter(v8::Local<v8::S
tring> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
194 { | 97 { |
195 // First look for API defined attributes on the style declaration object. | 98 CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); |
196 if (info.Holder()->HasRealNamedCallbackProperty(name)) | 99 String propertyName = toWebCoreString(name); |
197 return v8Undefined(); | 100 CSSPropertyInfo* propInfo = CSSStyleDeclaration::cssPropertyInfo(propertyNam
e); |
198 | |
199 // Search the style declaration. | |
200 CSSPropertyInfo* propInfo = cssPropertyInfo(name); | |
201 | |
202 // Do not handle non-property names. | |
203 if (!propInfo) | 101 if (!propInfo) |
204 return v8Undefined(); | 102 return v8Undefined(); |
205 | 103 |
206 CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); | |
207 RefPtr<CSSValue> cssValue = imp->getPropertyCSSValueInternal(static_cast<CSS
PropertyID>(propInfo->propID)); | |
208 if (cssValue) { | |
209 if (propInfo->hadPixelOrPosPrefix && | |
210 cssValue->isPrimitiveValue()) { | |
211 return v8::Number::New(static_cast<CSSPrimitiveValue*>( | |
212 cssValue.get())->getFloatValue(CSSPrimitiveValue::CSS_PX)); | |
213 } | |
214 return v8StringOrNull(cssValue->cssText(), info.GetIsolate()); | |
215 } | |
216 | |
217 String result = imp->getPropertyValueInternal(static_cast<CSSPropertyID>(pro
pInfo->propID)); | |
218 if (result.isNull()) | |
219 result = ""; // convert null to empty string. | |
220 | |
221 return v8String(result, info.GetIsolate()); | |
222 } | |
223 | |
224 v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertySetter(v8::Local<v8::S
tring> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) | |
225 { | |
226 CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); | |
227 CSSPropertyInfo* propInfo = cssPropertyInfo(name); | |
228 if (!propInfo) | |
229 return v8Undefined(); | |
230 | |
231 String propertyValue = toWebCoreStringWithNullCheck(value); | 104 String propertyValue = toWebCoreStringWithNullCheck(value); |
232 if (propInfo->hadPixelOrPosPrefix) | 105 if (propInfo->hadPixelOrPosPrefix) |
233 propertyValue.append("px"); | 106 propertyValue.append("px"); |
234 | 107 |
235 ExceptionCode ec = 0; | 108 ExceptionCode ec = 0; |
236 imp->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), prope
rtyValue, false, ec); | 109 imp->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), prope
rtyValue, false, ec); |
237 | 110 |
238 if (ec) | 111 if (ec) |
239 setDOMException(ec, info.GetIsolate()); | 112 setDOMException(ec, info.GetIsolate()); |
240 | 113 |
241 return value; | 114 return value; |
242 } | 115 } |
243 | 116 |
244 } // namespace WebCore | 117 } // namespace WebCore |
OLD | NEW |