OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "config.h" | |
6 #include "core/css/CSSStyleDeclaration.h" | |
7 | |
8 #include "core/css/CSSPropertyMetadata.h" | |
9 #include "core/css/parser/CSSParser.h" | |
10 #include "core/frame/UseCounter.h" | |
11 #include "wtf/text/WTFString.h" | |
12 | |
13 using namespace WTF; | |
14 | |
15 namespace blink { | |
16 | |
17 // Check for a CSS prefix. | |
18 // Passed prefix is all lowercase. | |
19 // First character of the prefix within the property name may be upper or lowerc ase. | |
20 // Other characters in the prefix within the property name must be lowercase. | |
21 // The prefix within the property name must be followed by a capital letter. | |
22 static bool hasCSSPropertyNamePrefix(const String& propertyName, const char* pre fix) | |
23 { | |
24 #if ENABLE(ASSERT) | |
25 ASSERT(*prefix); | |
26 for (const char* p = prefix; *p; ++p) | |
27 ASSERT(isASCIILower(*p)); | |
28 ASSERT(propertyName.length()); | |
29 #endif | |
30 | |
31 if (toASCIILower(propertyName[0]) != prefix[0]) | |
32 return false; | |
33 | |
34 unsigned length = propertyName.length(); | |
35 for (unsigned i = 1; i < length; ++i) { | |
36 if (!prefix[i]) | |
37 return isASCIIUpper(propertyName[i]); | |
38 if (propertyName[i] != prefix[i]) | |
39 return false; | |
40 } | |
41 return false; | |
42 } | |
43 | |
44 static CSSPropertyID parseCSSPropertyID(v8::Isolate* isolate, const String& prop ertyName) | |
45 { | |
46 unsigned length = propertyName.length(); | |
47 if (!length) | |
48 return CSSPropertyInvalid; | |
49 | |
50 StringBuilder builder; | |
51 builder.reserveCapacity(length); | |
52 | |
53 unsigned i = 0; | |
54 bool hasSeenDash = false; | |
55 | |
56 if (hasCSSPropertyNamePrefix(propertyName, "css")) { | |
57 i += 3; | |
58 // getComputedStyle(elem).cssX is a non-standard behaviour | |
59 // Measure this behaviour as CSSXGetComputedStyleQueries. | |
60 UseCounter::countIfNotPrivateScript(isolate, callingExecutionContext(iso late), UseCounter::CSSXGetComputedStyleQueries); | |
61 } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")) { | |
62 builder.append('-'); | |
63 } else if (isASCIIUpper(propertyName[0])) { | |
64 return CSSPropertyInvalid; | |
65 } | |
66 | |
67 bool hasSeenUpper = isASCIIUpper(propertyName[i]); | |
68 | |
69 builder.append(toASCIILower(propertyName[i++])); | |
70 | |
71 for (; i < length; ++i) { | |
72 UChar c = propertyName[i]; | |
73 if (!isASCIIUpper(c)) { | |
74 if (c == '-') | |
75 hasSeenDash = true; | |
76 builder.append(c); | |
77 } else { | |
78 hasSeenUpper = true; | |
79 builder.append('-'); | |
80 builder.append(toASCIILower(c)); | |
81 } | |
82 } | |
83 | |
84 // Reject names containing both dashes and upper-case characters, such as "b order-rightColor". | |
85 if (hasSeenDash && hasSeenUpper) | |
86 return CSSPropertyInvalid; | |
87 | |
88 String propName = builder.toString(); | |
89 return unresolvedCSSPropertyID(propName); | |
90 } | |
91 | |
92 static CSSPropertyID cssPropertyInfo(const String& propertyName, v8::Isolate* is olate) | |
93 { | |
94 typedef HashMap<String, CSSPropertyID> CSSPropertyIDMap; | |
95 DEFINE_STATIC_LOCAL(CSSPropertyIDMap, map, ()); | |
96 CSSPropertyIDMap::iterator iter = map.find(propertyName); | |
97 if (iter != map.end()) | |
98 return iter->value; | |
99 | |
100 CSSPropertyID unresolvedProperty = parseCSSPropertyID(isolate, propertyName) ; | |
101 map.add(propertyName, unresolvedProperty); | |
102 ASSERT(!unresolvedProperty || CSSPropertyMetadata::isEnabledProperty(unresol vedProperty)); | |
103 return unresolvedProperty; | |
104 } | |
105 | |
106 void CSSStyleDeclaration::anonymousNamedGetter(ScriptState* scriptState, const A tomicString& name, StringOrFloat& result) | |
107 { | |
108 // Search the style declaration. | |
109 CSSPropertyID unresolvedProperty = cssPropertyInfo(name, scriptState->isolat e()); | |
110 | |
111 // Do not handle non-property names. | |
112 if (!unresolvedProperty) | |
113 return; | |
114 CSSPropertyID resolvedProperty = resolveCSSPropertyID(unresolvedProperty); | |
115 | |
116 RefPtrWillBeRawPtr<CSSValue> cssValue = getPropertyCSSValueInternal(resolved Property); | |
117 if (cssValue) { | |
118 result.setString(cssValue->cssText()); | |
haraken
2015/04/29 15:53:46
The previous code was using v8SetReturnValueString
| |
119 return; | |
120 } | |
121 | |
122 result.setString(getPropertyValueInternal(resolvedProperty)); | |
123 } | |
124 | |
125 bool CSSStyleDeclaration::anonymousNamedSetter(ScriptState* scriptState, const S tring& name, const String& propertyValue, ExceptionState& exceptionState) | |
126 { | |
127 CSSPropertyID unresolvedProperty = cssPropertyInfo(name, scriptState->isolat e()); | |
128 if (!unresolvedProperty) | |
129 return false; | |
130 | |
131 setPropertyInternal(unresolvedProperty, propertyValue, false, exceptionState ); | |
haraken
2015/04/29 15:53:45
Don't we need:
if (exceptionState.throwIfNeeded
Jens Widell
2015/04/30 13:14:13
We do not. It's the outermost layer's job to actua
| |
132 return true; | |
133 } | |
134 | |
135 bool CSSStyleDeclaration::namedPropertyQuery(ScriptState* scriptState, const Ato micString& name, ExceptionState&) | |
136 { | |
137 if (!name.length()) | |
haraken
2015/04/29 15:53:45
Did we have this check in the previous code?
| |
138 return false; | |
139 // NOTE: cssPropertyInfo lookups incur several mallocs. | |
140 // Successful lookups have the same cost the first time, but are cached. | |
141 return cssPropertyInfo(name, scriptState->isolate()); | |
haraken
2015/04/29 15:53:45
In the previous code, we're doing v8SetReturnValue
| |
142 } | |
143 | |
144 void CSSStyleDeclaration::namedPropertyEnumerator(Vector<String>& names, Excepti onState&) | |
145 { | |
146 typedef Vector<String, numCSSProperties - 1> PreAllocatedPropertyVector; | |
147 DEFINE_STATIC_LOCAL(PreAllocatedPropertyVector, propertyNames, ()); | |
148 static unsigned propertyNamesLength = 0; | |
149 | |
150 if (propertyNames.isEmpty()) { | |
151 for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) { | |
152 CSSPropertyID propertyId = static_cast<CSSPropertyID>(id); | |
153 if (CSSPropertyMetadata::isEnabledProperty(propertyId)) | |
154 propertyNames.append(getJSPropertyName(propertyId)); | |
155 } | |
156 std::sort(propertyNames.begin(), propertyNames.end(), codePointCompareLe ssThan); | |
157 propertyNamesLength = propertyNames.size(); | |
158 } | |
159 | |
160 for (unsigned i = 0; i < propertyNamesLength; ++i) { | |
161 String key = propertyNames.at(i); | |
162 ASSERT(!key.isNull()); | |
163 names.append(key); | |
164 } | |
165 } | |
166 | |
167 } | |
haraken
2015/04/29 15:53:45
// namespace blink
| |
OLD | NEW |