| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 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 | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. 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 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| 11 * notice, this list of conditions and the following disclaimer in the | 11 * notice, this list of conditions and the following disclaimer in the |
| 12 * documentation and/or other materials provided with the distribution. | 12 * documentation and/or other materials provided with the distribution. |
| 13 * | 13 * |
| 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "config.h" | 26 #include "config.h" |
| 27 #include "modules/indexeddb/IDBCursor.h" | 27 #include "modules/indexeddb/IDBCursor.h" |
| 28 | 28 |
| 29 #include "bindings/v8/ExceptionMessages.h" | |
| 30 #include "bindings/v8/ExceptionState.h" | 29 #include "bindings/v8/ExceptionState.h" |
| 31 #include "bindings/v8/IDBBindingUtilities.h" | 30 #include "bindings/v8/IDBBindingUtilities.h" |
| 32 #include "core/dom/ExceptionCode.h" | 31 #include "core/dom/ExceptionCode.h" |
| 33 #include "core/dom/ExecutionContext.h" | 32 #include "core/dom/ExecutionContext.h" |
| 34 #include "core/inspector/ScriptCallStack.h" | 33 #include "core/inspector/ScriptCallStack.h" |
| 35 #include "modules/indexeddb/IDBAny.h" | 34 #include "modules/indexeddb/IDBAny.h" |
| 36 #include "modules/indexeddb/IDBDatabase.h" | 35 #include "modules/indexeddb/IDBDatabase.h" |
| 37 #include "modules/indexeddb/IDBKey.h" | 36 #include "modules/indexeddb/IDBKey.h" |
| 38 #include "modules/indexeddb/IDBObjectStore.h" | 37 #include "modules/indexeddb/IDBObjectStore.h" |
| 39 #include "modules/indexeddb/IDBRequest.h" | 38 #include "modules/indexeddb/IDBRequest.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 | 100 |
| 102 IDBCursor::~IDBCursor() | 101 IDBCursor::~IDBCursor() |
| 103 { | 102 { |
| 104 } | 103 } |
| 105 | 104 |
| 106 PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value,
ExceptionState& exceptionState) | 105 PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value,
ExceptionState& exceptionState) |
| 107 { | 106 { |
| 108 IDB_TRACE("IDBCursor::update"); | 107 IDB_TRACE("IDBCursor::update"); |
| 109 | 108 |
| 110 if (!m_gotValue) { | 109 if (!m_gotValue) { |
| 111 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 110 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 112 return 0; | 111 return 0; |
| 113 } | 112 } |
| 114 if (isKeyCursor()) { | 113 if (isKeyCursor()) { |
| 115 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::isKeyCursorErrorMessage)); | 114 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::isKeyCu
rsorErrorMessage); |
| 116 return 0; | 115 return 0; |
| 117 } | 116 } |
| 118 if (isDeleted()) { | 117 if (isDeleted()) { |
| 119 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 118 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 120 return 0; | 119 return 0; |
| 121 } | 120 } |
| 122 if (m_transaction->isFinished()) { | 121 if (m_transaction->isFinished()) { |
| 123 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("update", "IDBCursor", IDBDatabase::transactionFinishedErr
orMessage)); | 122 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 124 return 0; | 123 return 0; |
| 125 } | 124 } |
| 126 if (!m_transaction->isActive()) { | 125 if (!m_transaction->isActive()) { |
| 127 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("update", "IDBCursor", IDBDatabase::transactionInactiveErr
orMessage)); | 126 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 128 return 0; | 127 return 0; |
| 129 } | 128 } |
| 130 if (m_transaction->isReadOnly()) { | 129 if (m_transaction->isReadOnly()) { |
| 131 exceptionState.throwDOMException(ReadOnlyError, ExceptionMessages::faile
dToExecute("update", "IDBCursor", "The record may not be updated inside a read-o
nly transaction.")); | 130 exceptionState.throwDOMException(ReadOnlyError, "The record may not be u
pdated inside a read-only transaction."); |
| 132 return 0; | 131 return 0; |
| 133 } | 132 } |
| 134 | 133 |
| 135 RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); | 134 RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); |
| 136 const IDBKeyPath& keyPath = objectStore->metadata().keyPath; | 135 const IDBKeyPath& keyPath = objectStore->metadata().keyPath; |
| 137 const bool usesInLineKeys = !keyPath.isNull(); | 136 const bool usesInLineKeys = !keyPath.isNull(); |
| 138 if (usesInLineKeys) { | 137 if (usesInLineKeys) { |
| 139 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(m_requ
est->requestState(), value, keyPath); | 138 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(m_requ
est->requestState(), value, keyPath); |
| 140 if (!keyPathKey || !keyPathKey->isEqual(m_primaryKey.get())) { | 139 if (!keyPathKey || !keyPathKey->isEqual(m_primaryKey.get())) { |
| 141 exceptionState.throwDOMException(DataError, ExceptionMessages::faile
dToExecute("update", "IDBCursor", "The effective object store of this cursor use
s in-line keys and evaluating the key path of the value parameter results in a d
ifferent value than the cursor's effective key.")); | 140 exceptionState.throwDOMException(DataError, "The effective object st
ore of this cursor uses in-line keys and evaluating the key path of the value pa
rameter results in a different value than the cursor's effective key."); |
| 142 return 0; | 141 return 0; |
| 143 } | 142 } |
| 144 } | 143 } |
| 145 | 144 |
| 146 return objectStore->put(WebIDBDatabase::CursorUpdate, IDBAny::create(this),
state, value, m_primaryKey, exceptionState); | 145 return objectStore->put(WebIDBDatabase::CursorUpdate, IDBAny::create(this),
state, value, m_primaryKey, exceptionState); |
| 147 } | 146 } |
| 148 | 147 |
| 149 void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) | 148 void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) |
| 150 { | 149 { |
| 151 IDB_TRACE("IDBCursor::advance"); | 150 IDB_TRACE("IDBCursor::advance"); |
| 152 if (!m_gotValue) { | 151 if (!m_gotValue) { |
| 153 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("advance", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 152 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 154 return; | 153 return; |
| 155 } | 154 } |
| 156 if (isDeleted()) { | 155 if (isDeleted()) { |
| 157 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("advance", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 156 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 158 return; | 157 return; |
| 159 } | 158 } |
| 160 | 159 |
| 161 if (m_transaction->isFinished()) { | 160 if (m_transaction->isFinished()) { |
| 162 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("advance", "IDBCursor", IDBDatabase::transactionFinishedEr
rorMessage)); | 161 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 163 return; | 162 return; |
| 164 } | 163 } |
| 165 if (!m_transaction->isActive()) { | 164 if (!m_transaction->isActive()) { |
| 166 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("advance", "IDBCursor", IDBDatabase::transactionInactiveEr
rorMessage)); | 165 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 167 return; | 166 return; |
| 168 } | 167 } |
| 169 | 168 |
| 170 if (!count) { | 169 if (!count) { |
| 171 exceptionState.throwUninformativeAndGenericTypeError(); | 170 exceptionState.throwUninformativeAndGenericTypeError(); |
| 172 return; | 171 return; |
| 173 } | 172 } |
| 174 | 173 |
| 175 m_request->setPendingCursor(this); | 174 m_request->setPendingCursor(this); |
| 176 m_gotValue = false; | 175 m_gotValue = false; |
| 177 m_backend->advance(count, WebIDBCallbacksImpl::create(m_request).leakPtr()); | 176 m_backend->advance(count, WebIDBCallbacksImpl::create(m_request).leakPtr()); |
| 178 } | 177 } |
| 179 | 178 |
| 180 void IDBCursor::continueFunction(ExecutionContext* context, const ScriptValue& k
eyValue, ExceptionState& exceptionState) | 179 void IDBCursor::continueFunction(ExecutionContext* context, const ScriptValue& k
eyValue, ExceptionState& exceptionState) |
| 181 { | 180 { |
| 182 DOMRequestState requestState(context); | 181 DOMRequestState requestState(context); |
| 183 RefPtr<IDBKey> key = keyValue.isUndefined() ? 0 : scriptValueToIDBKey(&reque
stState, keyValue); | 182 RefPtr<IDBKey> key = keyValue.isUndefined() ? 0 : scriptValueToIDBKey(&reque
stState, keyValue); |
| 184 continueFunction(key.release(), exceptionState); | 183 continueFunction(key.release(), exceptionState); |
| 185 } | 184 } |
| 186 | 185 |
| 187 void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionState& excepti
onState) | 186 void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionState& excepti
onState) |
| 188 { | 187 { |
| 189 IDB_TRACE("IDBCursor::continue"); | 188 IDB_TRACE("IDBCursor::continue"); |
| 190 if (key && !key->isValid()) { | 189 if (key && !key->isValid()) { |
| 191 exceptionState.throwDOMException(DataError, ExceptionMessages::failedToE
xecute("continue", "IDBCursor", IDBDatabase::notValidKeyErrorMessage)); | 190 exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErro
rMessage); |
| 192 return; | 191 return; |
| 193 } | 192 } |
| 194 | 193 |
| 195 if (m_transaction->isFinished()) { | 194 if (m_transaction->isFinished()) { |
| 196 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("continue", "IDBCursor", IDBDatabase::transactionFinishedE
rrorMessage)); | 195 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 197 return; | 196 return; |
| 198 } | 197 } |
| 199 if (!m_transaction->isActive()) { | 198 if (!m_transaction->isActive()) { |
| 200 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("continue", "IDBCursor", IDBDatabase::transactionInactiveE
rrorMessage)); | 199 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 201 return; | 200 return; |
| 202 } | 201 } |
| 203 | 202 |
| 204 if (!m_gotValue) { | 203 if (!m_gotValue) { |
| 205 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 204 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 206 return; | 205 return; |
| 207 } | 206 } |
| 208 | 207 |
| 209 if (isDeleted()) { | 208 if (isDeleted()) { |
| 210 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage))
; | 209 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 211 return; | 210 return; |
| 212 } | 211 } |
| 213 | 212 |
| 214 if (key) { | 213 if (key) { |
| 215 ASSERT(m_key); | 214 ASSERT(m_key); |
| 216 if (m_direction == IndexedDB::CursorNext || m_direction == IndexedDB::Cu
rsorNextNoDuplicate) { | 215 if (m_direction == IndexedDB::CursorNext || m_direction == IndexedDB::Cu
rsorNextNoDuplicate) { |
| 217 if (!m_key->isLessThan(key.get())) { | 216 if (!m_key->isLessThan(key.get())) { |
| 218 exceptionState.throwDOMException(DataError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", "The parameter is less than or equal to
this cursor's position.")); | 217 exceptionState.throwDOMException(DataError, "The parameter is le
ss than or equal to this cursor's position."); |
| 219 return; | 218 return; |
| 220 } | 219 } |
| 221 } else { | 220 } else { |
| 222 if (!key->isLessThan(m_key.get())) { | 221 if (!key->isLessThan(m_key.get())) { |
| 223 exceptionState.throwDOMException(DataError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", "The parameter is greater than or equal
to this cursor's position.")); | 222 exceptionState.throwDOMException(DataError, "The parameter is gr
eater than or equal to this cursor's position."); |
| 224 return; | 223 return; |
| 225 } | 224 } |
| 226 } | 225 } |
| 227 } | 226 } |
| 228 | 227 |
| 229 // FIXME: We're not using the context from when continue was called, which m
eans the callback | 228 // FIXME: We're not using the context from when continue was called, which m
eans the callback |
| 230 // will be on the original context openCursor was called on. Is this
right? | 229 // will be on the original context openCursor was called on. Is this
right? |
| 231 m_request->setPendingCursor(this); | 230 m_request->setPendingCursor(this); |
| 232 m_gotValue = false; | 231 m_gotValue = false; |
| 233 m_backend->continueFunction(key, WebIDBCallbacksImpl::create(m_request).leak
Ptr()); | 232 m_backend->continueFunction(key, WebIDBCallbacksImpl::create(m_request).leak
Ptr()); |
| 234 } | 233 } |
| 235 | 234 |
| 236 PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, Exce
ptionState& exceptionState) | 235 PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, Exce
ptionState& exceptionState) |
| 237 { | 236 { |
| 238 IDB_TRACE("IDBCursor::delete"); | 237 IDB_TRACE("IDBCursor::delete"); |
| 239 if (m_transaction->isFinished()) { | 238 if (m_transaction->isFinished()) { |
| 240 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("delete", "IDBCursor", IDBDatabase::transactionFinishedErr
orMessage)); | 239 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 241 return 0; | 240 return 0; |
| 242 } | 241 } |
| 243 if (!m_transaction->isActive()) { | 242 if (!m_transaction->isActive()) { |
| 244 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("delete", "IDBCursor", IDBDatabase::transactionInactiveErr
orMessage)); | 243 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 245 return 0; | 244 return 0; |
| 246 } | 245 } |
| 247 if (m_transaction->isReadOnly()) { | 246 if (m_transaction->isReadOnly()) { |
| 248 exceptionState.throwDOMException(ReadOnlyError, ExceptionMessages::faile
dToExecute("delete", "IDBCursor", "The record may not be deleted inside a read-o
nly transaction.")); | 247 exceptionState.throwDOMException(ReadOnlyError, "The record may not be d
eleted inside a read-only transaction."); |
| 249 return 0; | 248 return 0; |
| 250 } | 249 } |
| 251 | 250 |
| 252 if (!m_gotValue) { | 251 if (!m_gotValue) { |
| 253 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 252 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 254 return 0; | 253 return 0; |
| 255 } | 254 } |
| 256 if (isKeyCursor()) { | 255 if (isKeyCursor()) { |
| 257 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::isKeyCursorErrorMessage)); | 256 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::isKeyCu
rsorErrorMessage); |
| 258 return 0; | 257 return 0; |
| 259 } | 258 } |
| 260 if (isDeleted()) { | 259 if (isDeleted()) { |
| 261 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 260 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 262 return 0; | 261 return 0; |
| 263 } | 262 } |
| 264 | 263 |
| 265 RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(m_primaryKey, exceptionStat
e); | 264 RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(m_primaryKey, exceptionStat
e); |
| 266 ASSERT(!exceptionState.hadException()); | 265 ASSERT(!exceptionState.hadException()); |
| 267 | 266 |
| 268 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this
), m_transaction.get()); | 267 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this
), m_transaction.get()); |
| 269 m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObject
Store()->id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr(
)); | 268 m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObject
Store()->id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr(
)); |
| 270 return request.release(); | 269 return request.release(); |
| 271 } | 270 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 case IndexedDB::CursorPrevNoDuplicate: | 398 case IndexedDB::CursorPrevNoDuplicate: |
| 400 return IDBCursor::directionPrevUnique(); | 399 return IDBCursor::directionPrevUnique(); |
| 401 | 400 |
| 402 default: | 401 default: |
| 403 ASSERT_NOT_REACHED(); | 402 ASSERT_NOT_REACHED(); |
| 404 return IDBCursor::directionNext(); | 403 return IDBCursor::directionNext(); |
| 405 } | 404 } |
| 406 } | 405 } |
| 407 | 406 |
| 408 } // namespace WebCore | 407 } // namespace WebCore |
| OLD | NEW |