Chromium Code Reviews| Index: Source/bindings/core/v8/ScriptPromiseProperty.h |
| diff --git a/Source/bindings/core/v8/ScriptPromiseProperty.h b/Source/bindings/core/v8/ScriptPromiseProperty.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f7aaa4b07da0f0db98aa02cca5179a12a457a2cf |
| --- /dev/null |
| +++ b/Source/bindings/core/v8/ScriptPromiseProperty.h |
| @@ -0,0 +1,135 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#ifndef ScriptPromiseProperty_h |
| +#define ScriptPromiseProperty_h |
| + |
| +#include "bindings/core/v8/ScriptPromise.h" |
| +#include "bindings/core/v8/ScriptPromisePropertyBase.h" |
| +#include "bindings/core/v8/V8Binding.h" |
| +#include "wtf/Noncopyable.h" |
| +#include "wtf/PassRefPtr.h" |
| + |
| +namespace WebCore { |
| + |
| +class ExecutionContext; |
| + |
| +// ScriptPromiseProperty is a helper for implementing a DOM method or |
| +// attribute whose value is a Promise, and the same Promise must be |
|
haraken
2014/07/02 09:04:31
whose value is a Promise => that returns a Promise
|
| +// returned each time. |
| +// |
| +// ScriptPromiseProperty does not keep Promises or worlds alive to |
| +// deliver Promise resolution/rejection to them; the Promise |
| +// resolution/rejections are delivered if the wrapper for the object |
| +// with the property is alive. This is achieved by keeping a weak |
|
haraken
2014/07/02 09:04:31
the wrapper for the object with the property => th
|
| +// reference from ScriptPromiseProperty to the holder's wrapper, and |
| +// references in hidden values between the wrapper, promise and |
| +// resolver (coincidentally the Resolver and Promise may be the same |
| +// object, but that is an implementation detail of v8.) |
| +// |
| +// -----> Resolver |
| +// / |
| +// ScriptPromiseProperty - - -> Holder Wrapper <------. |
| +// \ | |
| +// -----> Promise |
| +// |
| +// To avoid exposing the action of the garbage collector to script, |
| +// you should keep the wrapper alive as long as a promise may be |
| +// settled. |
| +// |
| +// ScriptPromiseProperty only supports the main world. |
| +// FIXME: Implement support for isolated worlds. |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +class ScriptPromiseProperty : public ScriptPromisePropertyBase { |
| + WTF_MAKE_NONCOPYABLE(ScriptPromiseProperty); |
| +public: |
| + // Creates a ScriptPromiseProperty that will create Promises in |
| + // the specified ExecutionContext for a property of 'holder' |
| + // (typically ScriptPromiseProperty should be a member of the |
| + // property holder). 'name' must be a unique name for the hidden |
| + // value backing the property. |
| + template<typename PassHolderType> |
| + static PassRefPtrWillBeRawPtr<ScriptPromiseProperty<HolderType, ResolvedType, RejectedType> > create(ExecutionContext*, PassHolderType, const char* name); |
| + |
| + virtual ~ScriptPromiseProperty() { } |
| + |
| + template<typename PassResolvedType> |
| + void resolve(PassResolvedType); |
| + |
| + template<typename PassRejectedType> |
| + void reject(PassRejectedType); |
| + |
| +private: |
| + template<typename PassHolderType> |
| + ScriptPromiseProperty(ExecutionContext*, PassHolderType, const char* name); |
| + |
| + virtual v8::Handle<v8::Object> holder(v8::Handle<v8::Object> creationContext, v8::Isolate*) OVERRIDE; |
| + virtual v8::Handle<v8::Value> resolvedValue(v8::Handle<v8::Object> creationContext, v8::Isolate*) OVERRIDE; |
| + virtual v8::Handle<v8::Value> rejectedValue(v8::Handle<v8::Object> creationContext, v8::Isolate*) OVERRIDE; |
| + |
| + HolderType m_holder; |
| + ResolvedType m_resolved; |
| + RejectedType m_rejected; |
| +}; |
| + |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +template<typename PassHolderType> |
| +PassRefPtrWillBeRawPtr<ScriptPromiseProperty<HolderType, ResolvedType, RejectedType> > ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::create(ExecutionContext* executionContext, PassHolderType holder, const char* name) |
| +{ |
| + RefPtr<ScriptPromiseProperty<HolderType, ResolvedType, RejectedType> > property = adoptRef(new ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>(executionContext, holder, name)); |
| + return property.release(); |
|
haraken
2014/07/02 09:04:31
return adoptRef(new ScriptPromiseProperty(...));
|
| +} |
| + |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +template<typename PassHolderType> |
| +ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::ScriptPromiseProperty(ExecutionContext* executionContext, PassHolderType holder, const char* name) |
| + : ScriptPromisePropertyBase(executionContext, name) |
| + , m_holder(holder) |
| +{ |
| +} |
| + |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +template<typename PassResolvedType> |
| +void ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::resolve(PassResolvedType value) |
| +{ |
| + if (!(executionContext() && state() == Pending)) |
|
haraken
2014/07/02 09:04:31
Is it valid that resolve() is called while state()
dominicc (has gone to gerrit)
2014/07/03 02:13:39
I originally did it this way, but yhirano says thi
|
| + return; |
| + m_resolved = value; |
| + settle(Resolved); |
|
haraken
2014/07/02 09:04:31
settle => resolveOrReject (to align with the funct
|
| +} |
| + |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +template<typename PassRejectedType> |
| +void ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::reject(PassRejectedType value) |
| +{ |
| + if (!(executionContext() && state() == Pending)) |
| + return; |
| + m_rejected = value; |
| + settle(Rejected); |
| +} |
| + |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +v8::Handle<v8::Object> ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::holder(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
| +{ |
| + v8::Handle<v8::Value> value = V8ValueTraits<HolderType>::toV8Value(m_holder, creationContext, isolate); |
|
haraken
2014/07/02 09:04:31
Is it guaranteed that we're in a correct context w
dominicc (has gone to gerrit)
2014/07/03 02:13:39
Yes, the ScriptPromisePropertyBase::promise and ::
|
| + return value.As<v8::Object>(); |
| +} |
| + |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +v8::Handle<v8::Value> ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::resolvedValue(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
| +{ |
| + ASSERT(state() == Resolved); |
| + return V8ValueTraits<ResolvedType>::toV8Value(m_resolved, creationContext, isolate); |
| +} |
| + |
| +template<typename HolderType, typename ResolvedType, typename RejectedType> |
| +v8::Handle<v8::Value> ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::rejectedValue(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) |
| +{ |
| + ASSERT(state() == Rejected); |
| + return V8ValueTraits<RejectedType>::toV8Value(m_rejected, creationContext, isolate); |
| +} |
| + |
| +} // namespace WebCore |
| + |
| +#endif // ScriptPromiseProperty_h |