This source file includes following definitions.
- hasCSSPropertyNamePrefix
- cssResolvedPropertyID
- cssPropertyInfo
- namedPropertyEnumeratorCustom
- namedPropertyQueryCustom
- namedPropertyGetterCustom
- namedPropertySetterCustom
#include "config.h"
#include "V8CSSStyleDeclaration.h"
#include "CSSPropertyNames.h"
#include "bindings/v8/ExceptionState.h"
#include "bindings/v8/V8Binding.h"
#include "core/css/parser/BisonCSSParser.h"
#include "core/css/CSSPrimitiveValue.h"
#include "core/css/CSSStyleDeclaration.h"
#include "core/css/CSSValue.h"
#include "core/css/RuntimeCSSEnabled.h"
#include "core/events/EventTarget.h"
#include "wtf/ASCIICType.h"
#include "wtf/PassRefPtr.h"
#include "wtf/RefPtr.h"
#include "wtf/StdLibExtras.h"
#include "wtf/Vector.h"
#include "wtf/text/StringBuilder.h"
#include "wtf/text/StringConcatenate.h"
using namespace WTF;
using namespace std;
namespace WebCore {
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;
}
struct CSSPropertyInfo {
CSSPropertyID propID;
};
static CSSPropertyID cssResolvedPropertyID(const String& propertyName)
{
unsigned length = propertyName.length();
if (!length)
return CSSPropertyInvalid;
StringBuilder builder;
builder.reserveCapacity(length);
unsigned i = 0;
bool hasSeenDash = false;
if (hasCSSPropertyNamePrefix(propertyName, "css"))
i += 3;
else if (hasCSSPropertyNamePrefix(propertyName, "webkit"))
builder.append('-');
else if (isASCIIUpper(propertyName[0]))
return CSSPropertyInvalid;
bool hasSeenUpper = isASCIIUpper(propertyName[i]);
builder.append(toASCIILower(propertyName[i++]));
for (; i < length; ++i) {
UChar c = propertyName[i];
if (!isASCIIUpper(c)) {
if (c == '-')
hasSeenDash = true;
builder.append(c);
} else {
hasSeenUpper = true;
builder.append('-');
builder.append(toASCIILower(c));
}
}
if (hasSeenDash && hasSeenUpper)
return CSSPropertyInvalid;
String propName = builder.toString();
return cssPropertyID(propName);
}
static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String> v8PropertyName)
{
String propertyName = toCoreString(v8PropertyName);
typedef HashMap<String, CSSPropertyInfo*> CSSPropertyInfoMap;
DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ());
CSSPropertyInfo* propInfo = map.get(propertyName);
if (!propInfo) {
propInfo = new CSSPropertyInfo();
propInfo->propID = cssResolvedPropertyID(propertyName);
map.add(propertyName, propInfo);
}
if (propInfo->propID && RuntimeCSSEnabled::isCSSPropertyEnabled(propInfo->propID))
return propInfo;
return 0;
}
void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>& info)
{
typedef Vector<String, numCSSProperties - 1> PreAllocatedPropertyVector;
DEFINE_STATIC_LOCAL(PreAllocatedPropertyVector, propertyNames, ());
static unsigned propertyNamesLength = 0;
if (propertyNames.isEmpty()) {
for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) {
CSSPropertyID propertyId = static_cast<CSSPropertyID>(id);
if (RuntimeCSSEnabled::isCSSPropertyEnabled(propertyId))
propertyNames.append(getJSPropertyName(propertyId));
}
sort(propertyNames.begin(), propertyNames.end(), codePointCompareLessThan);
propertyNamesLength = propertyNames.size();
}
v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), propertyNamesLength);
for (unsigned i = 0; i < propertyNamesLength; ++i) {
String key = propertyNames.at(i);
ASSERT(!key.isNull());
properties->Set(v8::Integer::New(info.GetIsolate(), i), v8String(info.GetIsolate(), key));
}
v8SetReturnValue(info, properties);
}
void V8CSSStyleDeclaration::namedPropertyQueryCustom(v8::Local<v8::String> v8Name, const v8::PropertyCallbackInfo<v8::Integer>& info)
{
if (cssPropertyInfo(v8Name)) {
v8SetReturnValueInt(info, 0);
return;
}
}
void V8CSSStyleDeclaration::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
{
if (info.Holder()->HasRealNamedCallbackProperty(name))
return;
CSSPropertyInfo* propInfo = cssPropertyInfo(name);
if (!propInfo)
return;
CSSStyleDeclaration* impl = V8CSSStyleDeclaration::toNative(info.Holder());
RefPtrWillBeRawPtr<CSSValue> cssValue = impl->getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propInfo->propID));
if (cssValue) {
v8SetReturnValueStringOrNull(info, cssValue->cssText(), info.GetIsolate());
return;
}
String result = impl->getPropertyValueInternal(static_cast<CSSPropertyID>(propInfo->propID));
if (result.isNull())
result = "";
v8SetReturnValueString(info, result, info.GetIsolate());
}
void V8CSSStyleDeclaration::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
{
CSSStyleDeclaration* impl = V8CSSStyleDeclaration::toNative(info.Holder());
CSSPropertyInfo* propInfo = cssPropertyInfo(name);
if (!propInfo)
return;
V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, propertyValue, value);
ExceptionState exceptionState(ExceptionState::SetterContext, getPropertyName(static_cast<CSSPropertyID>(propInfo->propID)), "CSSStyleDeclaration", info.Holder(), info.GetIsolate());
impl->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), propertyValue, false, exceptionState);
if (exceptionState.throwIfNeeded())
return;
v8SetReturnValue(info, value);
}
}