Chromium Code Reviews| Index: Source/modules/cachestorage/Cache.cpp |
| diff --git a/Source/modules/cachestorage/Cache.cpp b/Source/modules/cachestorage/Cache.cpp |
| index 8a6d65ea6132c018f2bb19007a4ce6b435da63f5..eb994c7b5c2e175100be71cf54dc8d4ea113e5ff 100644 |
| --- a/Source/modules/cachestorage/Cache.cpp |
| +++ b/Source/modules/cachestorage/Cache.cpp |
| @@ -9,6 +9,7 @@ |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "bindings/core/v8/ScriptPromiseResolver.h" |
| #include "bindings/core/v8/ScriptState.h" |
| +#include "bindings/core/v8/V8Binding.h" |
| #include "bindings/core/v8/V8ThrowException.h" |
| #include "bindings/modules/v8/V8Response.h" |
| #include "core/dom/DOMException.h" |
| @@ -135,45 +136,41 @@ private: |
| RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| }; |
| -ScriptPromise rejectAsNotImplemented(ScriptState* scriptState) |
| -{ |
| - return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError, "Cache is not implemented")); |
| -} |
| - |
| } // namespace |
| class Cache::FetchResolvedForAdd final : public ScriptFunction { |
| public: |
| - static v8::Local<v8::Function> create(ScriptState* scriptState, Cache* cache, Request* request) |
| + static v8::Local<v8::Function> create(ScriptState* scriptState, Cache* cache, const HeapVector<Member<Request>>& requests) |
| { |
| - FetchResolvedForAdd* self = new FetchResolvedForAdd(scriptState, cache, request); |
| + FetchResolvedForAdd* self = new FetchResolvedForAdd(scriptState, cache, requests); |
| return self->bindToV8Function(); |
| } |
| ScriptValue call(ScriptValue value) override |
| { |
| - Response* response = V8Response::toImplWithTypeCheck(scriptState()->isolate(), value.v8Value()); |
| - ScriptPromise putPromise = m_cache->putImpl(scriptState(), HeapVector<Member<Request>>(1, m_request), HeapVector<Member<Response>>(1, response)); |
| + NonThrowableExceptionState exceptionState; |
| + HeapVector<Member<Response>> responses = toMemberNativeArray<Response, V8Response>(value.v8Value(), m_requests.size(), scriptState()->isolate(), exceptionState); |
| + ScriptPromise putPromise = m_cache->putImpl(scriptState(), m_requests, responses); |
| return ScriptValue(scriptState(), putPromise.v8Value()); |
| } |
| DEFINE_INLINE_VIRTUAL_TRACE() |
| { |
| visitor->trace(m_cache); |
| - visitor->trace(m_request); |
| + visitor->trace(m_requests); |
| ScriptFunction::trace(visitor); |
| } |
| private: |
| - FetchResolvedForAdd(ScriptState* scriptState, Cache* cache, Request* request) |
| + FetchResolvedForAdd(ScriptState* scriptState, Cache* cache, const HeapVector<Member<Request>>& requests) |
| : ScriptFunction(scriptState) |
| , m_cache(cache) |
| - , m_request(request) |
| + , m_requests(requests) |
| { |
| } |
| Member<Cache> m_cache; |
| - Member<Request> m_request; |
| + HeapVector<Member<Request>> m_requests; |
| }; |
| class Cache::BarrierCallbackForPut final : public GarbageCollectedFinalized<BarrierCallbackForPut> { |
| @@ -292,25 +289,32 @@ ScriptPromise Cache::matchAll(ScriptState* scriptState, const RequestInfo& reque |
| ScriptPromise Cache::add(ScriptState* scriptState, const RequestInfo& request, ExceptionState& exceptionState) |
| { |
| ASSERT(!request.isNull()); |
| - Request* newRequest; |
| + HeapVector<Member<Request>> requests; |
| if (request.isRequest()) { |
| - newRequest = request.getAsRequest(); |
| + requests.append(request.getAsRequest()); |
| } else { |
| - newRequest = Request::create(scriptState, request.getAsUSVString(), exceptionState); |
| - |
| + requests.append(Request::create(scriptState, request.getAsUSVString(), exceptionState)); |
| if (exceptionState.hadException()) |
| return ScriptPromise(); |
| } |
| - Vector<Request*> requestVector; |
| - requestVector.append(newRequest); |
| - return addAllImpl(scriptState, requestVector, exceptionState); |
| + return addAllImpl(scriptState, requests, exceptionState); |
| } |
| -ScriptPromise Cache::addAll(ScriptState* scriptState, const Vector<ScriptValue>& rawRequests) |
| +ScriptPromise Cache::addAll(ScriptState* scriptState, const HeapVector<RequestInfo>& rawRequests, ExceptionState& exceptionState) |
| { |
| - // FIXME: Implement this. |
| - return rejectAsNotImplemented(scriptState); |
| + HeapVector<Member<Request>> requests; |
| + for (RequestInfo request : rawRequests) { |
| + if (request.isRequest()) { |
| + requests.append(request.getAsRequest()); |
| + } else { |
| + requests.append(Request::create(scriptState, request.getAsUSVString(), exceptionState)); |
| + if (exceptionState.hadException()) |
| + return ScriptPromise(); |
| + } |
| + } |
| + |
| + return addAllImpl(scriptState, requests, exceptionState); |
| } |
| ScriptPromise Cache::deleteFunction(ScriptState* scriptState, const RequestInfo& request, const CacheQueryOptions& options, ExceptionState& exceptionState) |
| @@ -388,23 +392,123 @@ ScriptPromise Cache::matchAllImpl(ScriptState* scriptState, const Request* reque |
| return promise; |
| } |
| -ScriptPromise Cache::addAllImpl(ScriptState* scriptState, const Vector<Request*>& requests, ExceptionState& exceptionState) |
| -{ |
| - // TODO(gavinp,nhiroki): Implement addAll for more than one element. |
| - ASSERT(requests.size() == 1); |
| +// This class provides Promise.all() for ScriptPromise. |
| +class ScriptPromiseAll final : public GarbageCollectedFinalized<ScriptPromiseAll> { |
|
jkarlin
2015/06/26 19:40:28
I'm sad that we have to go through V8 to wait on t
nhiroki
2015/07/02 09:31:54
Done.
|
| +public: |
| + class AdapterFunction : public ScriptFunction { |
| + public: |
| + enum ResolveType { |
| + Fulfilled, |
| + Rejected, |
| + }; |
| + |
| + static v8::Local<v8::Function> create(ScriptState* scriptState, ResolveType resolveType, size_t index, ScriptPromiseAll* promiseAll) |
| + { |
| + AdapterFunction* self = new AdapterFunction(scriptState, resolveType, index, promiseAll); |
| + return self->bindToV8Function(); |
| + } |
| + |
| + DEFINE_INLINE_VIRTUAL_TRACE() |
| + { |
| + visitor->trace(m_promiseAll); |
| + ScriptFunction::trace(visitor); |
| + } |
| + |
| + private: |
| + AdapterFunction(ScriptState* scriptState, ResolveType resolveType, size_t index, ScriptPromiseAll* promiseAll) |
| + : ScriptFunction(scriptState) |
| + , m_resolveType(resolveType) |
| + , m_index(index) |
| + , m_promiseAll(promiseAll) { } |
| + |
| + ScriptValue call(ScriptValue value) override |
| + { |
| + if (m_resolveType == Fulfilled) { |
| + m_promiseAll->onFulfilled(m_index, value); |
| + } else { |
| + m_promiseAll->onRejected(value); |
| + } |
| + return ScriptValue(scriptState(), m_promiseAll->promise().v8Value()); |
| + } |
| + |
| + const ResolveType m_resolveType; |
| + const size_t m_index; |
| + Member<ScriptPromiseAll> m_promiseAll; |
| + }; |
| + |
| + ScriptPromiseAll(Vector<ScriptPromise> promises, PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver) |
| + : m_numberOfPendingPromises(promises.size()) |
| + , m_resolver(resolver) |
| + { |
| + m_values.resize(promises.size()); |
| + for (size_t i = 0; i < promises.size(); ++i) |
| + promises[i].then(createFulfillFunction(i), createRejectFunction()); |
| + } |
| + |
| + void onFulfilled(size_t index, const ScriptValue& value) |
| + { |
| + ASSERT(index < m_values.size()); |
| + if (m_isResolvedOrRejected) |
| + return; |
| + m_values[index] = value; |
| + if (--m_numberOfPendingPromises > 0) |
| + return; |
| + m_isResolvedOrRejected = true; |
| + m_resolver->resolve(m_values); |
| + } |
| + |
| + void onRejected(const ScriptValue& value) |
| + { |
| + if (m_isResolvedOrRejected) |
| + return; |
| + m_isResolvedOrRejected = true; |
| + m_resolver->reject(value); |
| + } |
| + |
| + v8::Local<v8::Function> createFulfillFunction(size_t index) |
|
jkarlin
2015/06/26 19:40:28
The create functions should be private
nhiroki
2015/07/02 09:31:54
Done.
|
| + { |
| + return AdapterFunction::create(m_resolver->scriptState(), AdapterFunction::Fulfilled, index, this); |
| + } |
| + |
| + v8::Local<v8::Function> createRejectFunction() |
| + { |
| + return AdapterFunction::create(m_resolver->scriptState(), AdapterFunction::Rejected, 0, this); |
| + } |
| + |
| + ScriptPromise promise() { return m_resolver->promise(); } |
| + DEFINE_INLINE_VIRTUAL_TRACE() |
| + { |
| + visitor->trace(m_resolver); |
| + visitor->trace(m_values); |
| + } |
| + |
| +private: |
| + size_t m_numberOfPendingPromises; |
| + RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver; |
| + bool m_isResolvedOrRejected = false; |
|
jkarlin
2015/06/26 19:40:28
I believe 'settled' is the term for a promise that
nhiroki
2015/07/02 09:31:54
Done.
|
| + Vector<ScriptValue> m_values; |
| +}; |
| + |
| +ScriptPromise Cache::addAllImpl(ScriptState* scriptState, const HeapVector<Member<Request>>& requests, ExceptionState& exceptionState) |
| +{ |
| Vector<RequestInfo> requestInfos; |
| requestInfos.resize(requests.size()); |
| + Vector<ScriptPromise> promises; |
| + promises.resize(requests.size()); |
| for (size_t i = 0; i < requests.size(); ++i) { |
| if (!requests[i]->url().protocolIsInHTTPFamily()) |
| return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Add/AddAll does not support schemes other than \"http\" or \"https\"")); |
| if (requests[i]->method() != "GET") |
| return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Add/AddAll only supports the GET request method.")); |
| requestInfos[i].setRequest(requests[i]); |
| + |
| + promises[i] = m_scopedFetcher->fetch(scriptState, requestInfos[i], Dictionary(), exceptionState); |
| } |
| - ScriptPromise fetchPromise = m_scopedFetcher->fetch(scriptState, requestInfos[0], Dictionary(), exceptionState); |
| - return fetchPromise.then(FetchResolvedForAdd::create(scriptState, this, requests[0])); |
| + RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); |
| + ScriptPromiseAll* promiseAll = new ScriptPromiseAll(promises, resolver.get()); |
| + return promiseAll->promise().then(FetchResolvedForAdd::create(scriptState, this, requests)); |
| } |
| ScriptPromise Cache::deleteImpl(ScriptState* scriptState, const Request* request, const CacheQueryOptions& options) |