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. |
57 | 58 |
| 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 } |
58 | 156 |
59 v8::Handle<v8::Array> V8CSSStyleDeclaration::namedPropertyEnumerator(const v8::A
ccessorInfo& info) | 157 v8::Handle<v8::Array> V8CSSStyleDeclaration::namedPropertyEnumerator(const v8::A
ccessorInfo& info) |
60 { | 158 { |
61 typedef Vector<String, numCSSProperties - 1> PreAllocatedPropertyVector; | 159 typedef Vector<String, numCSSProperties - 1> PreAllocatedPropertyVector; |
62 DEFINE_STATIC_LOCAL(PreAllocatedPropertyVector, propertyNames, ()); | 160 DEFINE_STATIC_LOCAL(PreAllocatedPropertyVector, propertyNames, ()); |
63 static unsigned propertyNamesLength = 0; | 161 static unsigned propertyNamesLength = 0; |
64 | 162 |
65 if (propertyNames.isEmpty()) { | 163 if (propertyNames.isEmpty()) { |
66 for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { | 164 for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { |
67 CSSPropertyID propertyId = static_cast<CSSPropertyID>(id); | 165 CSSPropertyID propertyId = static_cast<CSSPropertyID>(id); |
(...skipping 11 matching lines...) Expand all Loading... |
79 properties->Set(v8Integer(i, info.GetIsolate()), v8String(key, info.GetI
solate())); | 177 properties->Set(v8Integer(i, info.GetIsolate()), v8String(key, info.GetI
solate())); |
80 } | 178 } |
81 | 179 |
82 return properties; | 180 return properties; |
83 } | 181 } |
84 | 182 |
85 v8::Handle<v8::Integer> V8CSSStyleDeclaration::namedPropertyQuery(v8::Local<v8::
String> v8Name, const v8::AccessorInfo& info) | 183 v8::Handle<v8::Integer> V8CSSStyleDeclaration::namedPropertyQuery(v8::Local<v8::
String> v8Name, const v8::AccessorInfo& info) |
86 { | 184 { |
87 // NOTE: cssPropertyInfo lookups incur several mallocs. | 185 // NOTE: cssPropertyInfo lookups incur several mallocs. |
88 // Successful lookups have the same cost the first time, but are cached. | 186 // Successful lookups have the same cost the first time, but are cached. |
89 String propertyName = toWebCoreString(v8Name); | 187 if (cssPropertyInfo(v8Name)) |
90 if (CSSStyleDeclaration::cssPropertyInfo(propertyName)) | |
91 return v8Integer(0, info.GetIsolate()); | 188 return v8Integer(0, info.GetIsolate()); |
92 | 189 |
93 return v8::Handle<v8::Integer>(); | 190 return v8::Handle<v8::Integer>(); |
94 } | 191 } |
95 | 192 |
| 193 v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertyGetter(v8::Local<v8::S
tring> name, const v8::AccessorInfo& info) |
| 194 { |
| 195 // First look for API defined attributes on the style declaration object. |
| 196 if (info.Holder()->HasRealNamedCallbackProperty(name)) |
| 197 return v8Undefined(); |
| 198 |
| 199 // Search the style declaration. |
| 200 CSSPropertyInfo* propInfo = cssPropertyInfo(name); |
| 201 |
| 202 // Do not handle non-property names. |
| 203 if (!propInfo) |
| 204 return v8Undefined(); |
| 205 |
| 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); |
| 232 if (propInfo->hadPixelOrPosPrefix) |
| 233 propertyValue.append("px"); |
| 234 |
| 235 ExceptionCode ec = 0; |
| 236 imp->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), prope
rtyValue, false, ec); |
| 237 |
| 238 if (ec) |
| 239 setDOMException(ec, info.GetIsolate()); |
| 240 |
| 241 return value; |
| 242 } |
| 243 |
96 } // namespace WebCore | 244 } // namespace WebCore |
OLD | NEW |