| Index: Source/modules/cachestorage/Cache.cpp
|
| diff --git a/Source/modules/cachestorage/Cache.cpp b/Source/modules/cachestorage/Cache.cpp
|
| index d2c9e5fb112e1e5d0877272dd31c682680976102..0156b1486464503829001d6b316d76fc824d5144 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,141 @@ private:
|
| RefPtrWillBePersistent<ScriptPromiseResolver> m_resolver;
|
| };
|
|
|
| -ScriptPromise rejectAsNotImplemented(ScriptState* scriptState)
|
| -{
|
| - return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError, "Cache is not implemented"));
|
| -}
|
| +// This class provides Promise.all() for ScriptPromise.
|
| +// TODO(nhiroki): Move this somewhere else so that other components can reuse.
|
| +// TODO(nhiroki): Unfortunately, we have to go through V8 to wait for the fetch
|
| +// promise. It should be better to achieve this only within C++ world.
|
| +class CacheStoragePromiseAll final : public GarbageCollectedFinalized<CacheStoragePromiseAll> {
|
| +public:
|
| + CacheStoragePromiseAll(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_isSettled)
|
| + return;
|
| + m_values[index] = value;
|
| + if (--m_numberOfPendingPromises > 0)
|
| + return;
|
| + m_isSettled = true;
|
| + m_resolver->resolve(m_values);
|
| + }
|
| +
|
| + void onRejected(const ScriptValue& value)
|
| + {
|
| + if (m_isSettled)
|
| + return;
|
| + m_isSettled = true;
|
| + m_resolver->reject(value);
|
| + }
|
| +
|
| + ScriptPromise promise() { return m_resolver->promise(); }
|
| +
|
| + DEFINE_INLINE_VIRTUAL_TRACE()
|
| + {
|
| + visitor->trace(m_resolver);
|
| + visitor->trace(m_values);
|
| + }
|
| +
|
| +private:
|
| + class AdapterFunction : public ScriptFunction {
|
| + public:
|
| + enum ResolveType {
|
| + Fulfilled,
|
| + Rejected,
|
| + };
|
| +
|
| + static v8::Local<v8::Function> create(ScriptState* scriptState, ResolveType resolveType, size_t index, CacheStoragePromiseAll* 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, CacheStoragePromiseAll* 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<CacheStoragePromiseAll> m_promiseAll;
|
| + };
|
| +
|
| + v8::Local<v8::Function> createFulfillFunction(size_t index)
|
| + {
|
| + 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);
|
| + }
|
| +
|
| + size_t m_numberOfPendingPromises;
|
| + RefPtrWillBeMember<ScriptPromiseResolver> m_resolver;
|
| + bool m_isSettled = false;
|
| + Vector<ScriptValue> m_values;
|
| +};
|
|
|
| } // 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> {
|
| @@ -298,25 +395,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)
|
| @@ -394,23 +498,25 @@ ScriptPromise Cache::matchAllImpl(ScriptState* scriptState, const Request* reque
|
| return promise;
|
| }
|
|
|
| -ScriptPromise Cache::addAllImpl(ScriptState* scriptState, const Vector<Request*>& requests, ExceptionState& exceptionState)
|
| +ScriptPromise Cache::addAllImpl(ScriptState* scriptState, const HeapVector<Member<Request>>& requests, ExceptionState& exceptionState)
|
| {
|
| - // TODO(gavinp,nhiroki): Implement addAll for more than one element.
|
| - ASSERT(requests.size() == 1);
|
| -
|
| 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);
|
| + CacheStoragePromiseAll* promiseAll = new CacheStoragePromiseAll(promises, resolver.get());
|
| + return promiseAll->promise().then(FetchResolvedForAdd::create(scriptState, this, requests));
|
| }
|
|
|
| ScriptPromise Cache::deleteImpl(ScriptState* scriptState, const Request* request, const CacheQueryOptions& options)
|
|
|