| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 | 99 |
| 101 IDBCursor::~IDBCursor() | 100 IDBCursor::~IDBCursor() |
| 102 { | 101 { |
| 103 } | 102 } |
| 104 | 103 |
| 105 PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value,
ExceptionState& exceptionState) | 104 PassRefPtr<IDBRequest> IDBCursor::update(ScriptState* state, ScriptValue& value,
ExceptionState& exceptionState) |
| 106 { | 105 { |
| 107 IDB_TRACE("IDBCursor::update"); | 106 IDB_TRACE("IDBCursor::update"); |
| 108 | 107 |
| 109 if (!m_gotValue) { | 108 if (!m_gotValue) { |
| 110 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 109 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 111 return 0; | 110 return 0; |
| 112 } | 111 } |
| 113 if (isKeyCursor()) { | 112 if (isKeyCursor()) { |
| 114 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::isKeyCursorErrorMessage)); | 113 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::isKeyCu
rsorErrorMessage); |
| 115 return 0; | 114 return 0; |
| 116 } | 115 } |
| 117 if (isDeleted()) { | 116 if (isDeleted()) { |
| 118 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("update", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 117 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 119 return 0; | 118 return 0; |
| 120 } | 119 } |
| 121 if (m_transaction->isFinished()) { | 120 if (m_transaction->isFinished()) { |
| 122 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("update", "IDBCursor", IDBDatabase::transactionFinishedErr
orMessage)); | 121 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 123 return 0; | 122 return 0; |
| 124 } | 123 } |
| 125 if (!m_transaction->isActive()) { | 124 if (!m_transaction->isActive()) { |
| 126 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("update", "IDBCursor", IDBDatabase::transactionInactiveErr
orMessage)); | 125 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 127 return 0; | 126 return 0; |
| 128 } | 127 } |
| 129 if (m_transaction->isReadOnly()) { | 128 if (m_transaction->isReadOnly()) { |
| 130 exceptionState.throwDOMException(ReadOnlyError, ExceptionMessages::faile
dToExecute("update", "IDBCursor", "The record may not be updated inside a read-o
nly transaction.")); | 129 exceptionState.throwDOMException(ReadOnlyError, "The record may not be u
pdated inside a read-only transaction."); |
| 131 return 0; | 130 return 0; |
| 132 } | 131 } |
| 133 | 132 |
| 134 RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); | 133 RefPtr<IDBObjectStore> objectStore = effectiveObjectStore(); |
| 135 const IDBKeyPath& keyPath = objectStore->metadata().keyPath; | 134 const IDBKeyPath& keyPath = objectStore->metadata().keyPath; |
| 136 const bool usesInLineKeys = !keyPath.isNull(); | 135 const bool usesInLineKeys = !keyPath.isNull(); |
| 137 if (usesInLineKeys) { | 136 if (usesInLineKeys) { |
| 138 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(m_requ
est->requestState(), value, keyPath); | 137 RefPtr<IDBKey> keyPathKey = createIDBKeyFromScriptValueAndKeyPath(m_requ
est->requestState(), value, keyPath); |
| 139 if (!keyPathKey || !keyPathKey->isEqual(m_primaryKey.get())) { | 138 if (!keyPathKey || !keyPathKey->isEqual(m_primaryKey.get())) { |
| 140 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.")); | 139 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."); |
| 141 return 0; | 140 return 0; |
| 142 } | 141 } |
| 143 } | 142 } |
| 144 | 143 |
| 145 return objectStore->put(WebIDBDatabase::CursorUpdate, IDBAny::create(this),
state, value, m_primaryKey, exceptionState); | 144 return objectStore->put(WebIDBDatabase::CursorUpdate, IDBAny::create(this),
state, value, m_primaryKey, exceptionState); |
| 146 } | 145 } |
| 147 | 146 |
| 148 void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) | 147 void IDBCursor::advance(unsigned long count, ExceptionState& exceptionState) |
| 149 { | 148 { |
| 150 IDB_TRACE("IDBCursor::advance"); | 149 IDB_TRACE("IDBCursor::advance"); |
| 151 if (!m_gotValue) { | 150 if (!m_gotValue) { |
| 152 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("advance", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 151 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 153 return; | 152 return; |
| 154 } | 153 } |
| 155 if (isDeleted()) { | 154 if (isDeleted()) { |
| 156 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("advance", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 155 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 157 return; | 156 return; |
| 158 } | 157 } |
| 159 | 158 |
| 160 if (m_transaction->isFinished()) { | 159 if (m_transaction->isFinished()) { |
| 161 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("advance", "IDBCursor", IDBDatabase::transactionFinishedEr
rorMessage)); | 160 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 162 return; | 161 return; |
| 163 } | 162 } |
| 164 if (!m_transaction->isActive()) { | 163 if (!m_transaction->isActive()) { |
| 165 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("advance", "IDBCursor", IDBDatabase::transactionInactiveEr
rorMessage)); | 164 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 166 return; | 165 return; |
| 167 } | 166 } |
| 168 | 167 |
| 169 if (!count) { | 168 if (!count) { |
| 170 exceptionState.throwUninformativeAndGenericTypeError(); | 169 exceptionState.throwUninformativeAndGenericTypeError(); |
| 171 return; | 170 return; |
| 172 } | 171 } |
| 173 | 172 |
| 174 m_request->setPendingCursor(this); | 173 m_request->setPendingCursor(this); |
| 175 m_gotValue = false; | 174 m_gotValue = false; |
| 176 m_backend->advance(count, WebIDBCallbacksImpl::create(m_request).leakPtr()); | 175 m_backend->advance(count, WebIDBCallbacksImpl::create(m_request).leakPtr()); |
| 177 } | 176 } |
| 178 | 177 |
| 179 void IDBCursor::continueFunction(ExecutionContext* context, const ScriptValue& k
eyValue, ExceptionState& exceptionState) | 178 void IDBCursor::continueFunction(ExecutionContext* context, const ScriptValue& k
eyValue, ExceptionState& exceptionState) |
| 180 { | 179 { |
| 181 DOMRequestState requestState(context); | 180 DOMRequestState requestState(context); |
| 182 RefPtr<IDBKey> key = keyValue.isUndefined() ? 0 : scriptValueToIDBKey(&reque
stState, keyValue); | 181 RefPtr<IDBKey> key = keyValue.isUndefined() ? 0 : scriptValueToIDBKey(&reque
stState, keyValue); |
| 183 continueFunction(key.release(), exceptionState); | 182 continueFunction(key.release(), exceptionState); |
| 184 } | 183 } |
| 185 | 184 |
| 186 void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionState& excepti
onState) | 185 void IDBCursor::continueFunction(PassRefPtr<IDBKey> key, ExceptionState& excepti
onState) |
| 187 { | 186 { |
| 188 IDB_TRACE("IDBCursor::continue"); | 187 IDB_TRACE("IDBCursor::continue"); |
| 189 if (key && !key->isValid()) { | 188 if (key && !key->isValid()) { |
| 190 exceptionState.throwDOMException(DataError, ExceptionMessages::failedToE
xecute("continue", "IDBCursor", IDBDatabase::notValidKeyErrorMessage)); | 189 exceptionState.throwDOMException(DataError, IDBDatabase::notValidKeyErro
rMessage); |
| 191 return; | 190 return; |
| 192 } | 191 } |
| 193 | 192 |
| 194 if (m_transaction->isFinished()) { | 193 if (m_transaction->isFinished()) { |
| 195 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("continue", "IDBCursor", IDBDatabase::transactionFinishedE
rrorMessage)); | 194 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 196 return; | 195 return; |
| 197 } | 196 } |
| 198 if (!m_transaction->isActive()) { | 197 if (!m_transaction->isActive()) { |
| 199 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("continue", "IDBCursor", IDBDatabase::transactionInactiveE
rrorMessage)); | 198 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 200 return; | 199 return; |
| 201 } | 200 } |
| 202 | 201 |
| 203 if (!m_gotValue) { | 202 if (!m_gotValue) { |
| 204 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 203 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 205 return; | 204 return; |
| 206 } | 205 } |
| 207 | 206 |
| 208 if (isDeleted()) { | 207 if (isDeleted()) { |
| 209 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage))
; | 208 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 210 return; | 209 return; |
| 211 } | 210 } |
| 212 | 211 |
| 213 if (key) { | 212 if (key) { |
| 214 ASSERT(m_key); | 213 ASSERT(m_key); |
| 215 if (m_direction == IndexedDB::CursorNext || m_direction == IndexedDB::Cu
rsorNextNoDuplicate) { | 214 if (m_direction == IndexedDB::CursorNext || m_direction == IndexedDB::Cu
rsorNextNoDuplicate) { |
| 216 if (!m_key->isLessThan(key.get())) { | 215 if (!m_key->isLessThan(key.get())) { |
| 217 exceptionState.throwDOMException(DataError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", "The parameter is less than or equal to
this cursor's position.")); | 216 exceptionState.throwDOMException(DataError, "The parameter is le
ss than or equal to this cursor's position."); |
| 218 return; | 217 return; |
| 219 } | 218 } |
| 220 } else { | 219 } else { |
| 221 if (!key->isLessThan(m_key.get())) { | 220 if (!key->isLessThan(m_key.get())) { |
| 222 exceptionState.throwDOMException(DataError, ExceptionMessages::f
ailedToExecute("continue", "IDBCursor", "The parameter is greater than or equal
to this cursor's position.")); | 221 exceptionState.throwDOMException(DataError, "The parameter is gr
eater than or equal to this cursor's position."); |
| 223 return; | 222 return; |
| 224 } | 223 } |
| 225 } | 224 } |
| 226 } | 225 } |
| 227 | 226 |
| 228 // FIXME: We're not using the context from when continue was called, which m
eans the callback | 227 // FIXME: We're not using the context from when continue was called, which m
eans the callback |
| 229 // will be on the original context openCursor was called on. Is this
right? | 228 // will be on the original context openCursor was called on. Is this
right? |
| 230 m_request->setPendingCursor(this); | 229 m_request->setPendingCursor(this); |
| 231 m_gotValue = false; | 230 m_gotValue = false; |
| 232 m_backend->continueFunction(key, WebIDBCallbacksImpl::create(m_request).leak
Ptr()); | 231 m_backend->continueFunction(key, WebIDBCallbacksImpl::create(m_request).leak
Ptr()); |
| 233 } | 232 } |
| 234 | 233 |
| 235 PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, Exce
ptionState& exceptionState) | 234 PassRefPtr<IDBRequest> IDBCursor::deleteFunction(ExecutionContext* context, Exce
ptionState& exceptionState) |
| 236 { | 235 { |
| 237 IDB_TRACE("IDBCursor::delete"); | 236 IDB_TRACE("IDBCursor::delete"); |
| 238 if (m_transaction->isFinished()) { | 237 if (m_transaction->isFinished()) { |
| 239 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("delete", "IDBCursor", IDBDatabase::transactionFinishedErr
orMessage)); | 238 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionFinishedErrorMessage); |
| 240 return 0; | 239 return 0; |
| 241 } | 240 } |
| 242 if (!m_transaction->isActive()) { | 241 if (!m_transaction->isActive()) { |
| 243 exceptionState.throwDOMException(TransactionInactiveError, ExceptionMess
ages::failedToExecute("delete", "IDBCursor", IDBDatabase::transactionInactiveErr
orMessage)); | 242 exceptionState.throwDOMException(TransactionInactiveError, IDBDatabase::
transactionInactiveErrorMessage); |
| 244 return 0; | 243 return 0; |
| 245 } | 244 } |
| 246 if (m_transaction->isReadOnly()) { | 245 if (m_transaction->isReadOnly()) { |
| 247 exceptionState.throwDOMException(ReadOnlyError, ExceptionMessages::faile
dToExecute("delete", "IDBCursor", "The record may not be deleted inside a read-o
nly transaction.")); | 246 exceptionState.throwDOMException(ReadOnlyError, "The record may not be d
eleted inside a read-only transaction."); |
| 248 return 0; | 247 return 0; |
| 249 } | 248 } |
| 250 | 249 |
| 251 if (!m_gotValue) { | 250 if (!m_gotValue) { |
| 252 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::noValueErrorMessage)); | 251 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::noValue
ErrorMessage); |
| 253 return 0; | 252 return 0; |
| 254 } | 253 } |
| 255 if (isKeyCursor()) { | 254 if (isKeyCursor()) { |
| 256 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::isKeyCursorErrorMessage)); | 255 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::isKeyCu
rsorErrorMessage); |
| 257 return 0; | 256 return 0; |
| 258 } | 257 } |
| 259 if (isDeleted()) { | 258 if (isDeleted()) { |
| 260 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("delete", "IDBCursor", IDBDatabase::sourceDeletedErrorMessage)); | 259 exceptionState.throwDOMException(InvalidStateError, IDBDatabase::sourceD
eletedErrorMessage); |
| 261 return 0; | 260 return 0; |
| 262 } | 261 } |
| 263 | 262 |
| 264 RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(m_primaryKey, exceptionStat
e); | 263 RefPtr<IDBKeyRange> keyRange = IDBKeyRange::only(m_primaryKey, exceptionStat
e); |
| 265 ASSERT(!exceptionState.hadException()); | 264 ASSERT(!exceptionState.hadException()); |
| 266 | 265 |
| 267 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this
), m_transaction.get()); | 266 RefPtr<IDBRequest> request = IDBRequest::create(context, IDBAny::create(this
), m_transaction.get()); |
| 268 m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObject
Store()->id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr(
)); | 267 m_transaction->backendDB()->deleteRange(m_transaction->id(), effectiveObject
Store()->id(), keyRange.release(), WebIDBCallbacksImpl::create(request).leakPtr(
)); |
| 269 return request.release(); | 268 return request.release(); |
| 270 } | 269 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 case IndexedDB::CursorPrevNoDuplicate: | 397 case IndexedDB::CursorPrevNoDuplicate: |
| 399 return IDBCursor::directionPrevUnique(); | 398 return IDBCursor::directionPrevUnique(); |
| 400 | 399 |
| 401 default: | 400 default: |
| 402 ASSERT_NOT_REACHED(); | 401 ASSERT_NOT_REACHED(); |
| 403 return IDBCursor::directionNext(); | 402 return IDBCursor::directionNext(); |
| 404 } | 403 } |
| 405 } | 404 } |
| 406 | 405 |
| 407 } // namespace WebCore | 406 } // namespace WebCore |
| OLD | NEW |