Index: Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp |
diff --git a/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp |
index ae85a20d4c57ed1eaff1c1ac3a049872779e0712..6805ddd6912e986b96ef71dc3f6a324e5f762563 100644 |
--- a/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp |
+++ b/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp |
@@ -54,7 +54,105 @@ using namespace std; |
namespace WebCore { |
+// FIXME: Next two functions look lifted verbatim from JSCSSStyleDeclarationCustom. Please remove duplication. |
+// Check for a CSS prefix. |
+// Passed prefix is all lowercase. |
+// First character of the prefix within the property name may be upper or lowercase. |
+// Other characters in the prefix within the property name must be lowercase. |
+// The prefix within the property name must be followed by a capital letter. |
+static bool hasCSSPropertyNamePrefix(const String& propertyName, const char* prefix) |
+{ |
+#ifndef NDEBUG |
+ ASSERT(*prefix); |
+ for (const char* p = prefix; *p; ++p) |
+ ASSERT(isASCIILower(*p)); |
+ ASSERT(propertyName.length()); |
+#endif |
+ |
+ if (toASCIILower(propertyName[0]) != prefix[0]) |
+ return false; |
+ |
+ unsigned length = propertyName.length(); |
+ for (unsigned i = 1; i < length; ++i) { |
+ if (!prefix[i]) |
+ return isASCIIUpper(propertyName[i]); |
+ if (propertyName[i] != prefix[i]) |
+ return false; |
+ } |
+ return false; |
+} |
+ |
+class CSSPropertyInfo { |
+public: |
+ CSSPropertyID propID; |
+ bool hadPixelOrPosPrefix; |
+}; |
+ |
+// When getting properties on CSSStyleDeclarations, the name used from |
+// Javascript and the actual name of the property are not the same, so |
+// we have to do the following translation. The translation turns upper |
+// case characters into lower case characters and inserts dashes to |
+// separate words. |
+// |
+// Example: 'backgroundPositionY' -> 'background-position-y' |
+// |
+// Also, certain prefixes such as 'pos', 'css-' and 'pixel-' are stripped |
+// and the hadPixelOrPosPrefix out parameter is used to indicate whether or |
+// not the property name was prefixed with 'pos-' or 'pixel-'. |
+static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String> v8PropertyName) |
+{ |
+ String propertyName = toWebCoreString(v8PropertyName); |
+ typedef HashMap<String, CSSPropertyInfo*> CSSPropertyInfoMap; |
+ DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ()); |
+ CSSPropertyInfo* propInfo = map.get(propertyName); |
+ if (!propInfo) { |
+ unsigned length = propertyName.length(); |
+ bool hadPixelOrPosPrefix = false; |
+ if (!length) |
+ return 0; |
+ |
+ StringBuilder builder; |
+ builder.reserveCapacity(length); |
+ |
+ unsigned i = 0; |
+ |
+ if (hasCSSPropertyNamePrefix(propertyName, "css")) |
+ i += 3; |
+ else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) { |
+ i += 5; |
+ hadPixelOrPosPrefix = true; |
+ } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) { |
+ i += 3; |
+ hadPixelOrPosPrefix = true; |
+ } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")) |
+ builder.append('-'); |
+ else if (isASCIIUpper(propertyName[0])) |
+ return 0; |
+ |
+ builder.append(toASCIILower(propertyName[i++])); |
+ |
+ for (; i < length; ++i) { |
+ UChar c = propertyName[i]; |
+ if (!isASCIIUpper(c)) |
+ builder.append(c); |
+ else { |
+ builder.append('-'); |
+ builder.append(toASCIILower(c)); |
+ } |
+ } |
+ |
+ String propName = builder.toString(); |
+ CSSPropertyID propertyID = cssPropertyID(propName); |
+ if (propertyID && RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID)) { |
+ propInfo = new CSSPropertyInfo(); |
+ propInfo->hadPixelOrPosPrefix = hadPixelOrPosPrefix; |
+ propInfo->propID = propertyID; |
+ map.add(propertyName, propInfo); |
+ } |
+ } |
+ return propInfo; |
+} |
v8::Handle<v8::Array> V8CSSStyleDeclaration::namedPropertyEnumerator(const v8::AccessorInfo& info) |
{ |
@@ -86,11 +184,61 @@ v8::Handle<v8::Integer> V8CSSStyleDeclaration::namedPropertyQuery(v8::Local<v8:: |
{ |
// NOTE: cssPropertyInfo lookups incur several mallocs. |
// Successful lookups have the same cost the first time, but are cached. |
- String propertyName = toWebCoreString(v8Name); |
- if (CSSStyleDeclaration::cssPropertyInfo(propertyName)) |
+ if (cssPropertyInfo(v8Name)) |
return v8Integer(0, info.GetIsolate()); |
return v8::Handle<v8::Integer>(); |
} |
+v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertyGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) |
+{ |
+ // First look for API defined attributes on the style declaration object. |
+ if (info.Holder()->HasRealNamedCallbackProperty(name)) |
+ return v8Undefined(); |
+ |
+ // Search the style declaration. |
+ CSSPropertyInfo* propInfo = cssPropertyInfo(name); |
+ |
+ // Do not handle non-property names. |
+ if (!propInfo) |
+ return v8Undefined(); |
+ |
+ CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); |
+ RefPtr<CSSValue> cssValue = imp->getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); |
+ if (cssValue) { |
+ if (propInfo->hadPixelOrPosPrefix |
+ && cssValue->isPrimitiveValue()) { |
+ return v8::Number::New(static_cast<CSSPrimitiveValue*>( |
+ cssValue.get())->getFloatValue(CSSPrimitiveValue::CSS_PX)); |
+ } |
+ return v8StringOrNull(cssValue->cssText(), info.GetIsolate()); |
+ } |
+ |
+ String result = imp->getPropertyValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); |
+ if (result.isNull()) |
+ result = ""; // convert null to empty string. |
+ |
+ return v8String(result, info.GetIsolate()); |
+} |
+ |
+v8::Handle<v8::Value> V8CSSStyleDeclaration::namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info) |
+{ |
+ CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); |
+ CSSPropertyInfo* propInfo = cssPropertyInfo(name); |
+ if (!propInfo) |
+ return v8Undefined(); |
+ |
+ String propertyValue = toWebCoreStringWithNullCheck(value); |
+ if (propInfo->hadPixelOrPosPrefix) |
+ propertyValue.append("px"); |
+ |
+ ExceptionCode ec = 0; |
+ imp->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), propertyValue, false, ec); |
+ |
+ if (ec) |
+ setDOMException(ec, info.GetIsolate()); |
+ |
+ return value; |
+} |
+ |
} // namespace WebCore |