| 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
|
|
|