1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// 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/ToV8.h"
#include "wtf/Noncopyable.h"
#include "wtf/PassRefPtr.h"
namespace blink {
class ExecutionContext;
// ScriptPromiseProperty is a helper for implementing a DOM method or
// attribute whose value is a Promise, and the same Promise must be
// 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 holder's wrapper is
// alive. This is achieved by keeping a weak reference from
// ScriptPromiseProperty to the holder's wrapper, and references in
// hidden values from the wrapper to the 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.
//
// To avoid clobbering hidden values, a holder should only have one
// ScriptPromiseProperty object for a given name at a time. See reset.
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).
//
// When implementing a ScriptPromiseProperty add the property name
// to ScriptPromiseProperties.h and pass
// ScriptPromiseProperty::Foo to create. The name must be unique
// per kind of holder.
template<typename PassHolderType>
ScriptPromiseProperty(ExecutionContext*, PassHolderType, Name);
virtual ~ScriptPromiseProperty() { }
template<typename PassResolvedType>
void resolve(PassResolvedType);
template<typename PassRejectedType>
void reject(PassRejectedType);
// Resets this property by unregistering the Promise property from the
// holder wrapper. Resets the internal state to Pending and clears the
// resolved and the rejected values.
// This method keeps the holder object and the property name.
void reset();
virtual void trace(Visitor*) override;
private:
virtual v8::Handle<v8::Object> holder(v8::Handle<v8::Object> creationContext, v8::Isolate*) override;
virtual v8::Handle<v8::Value> resolvedValue(v8::Isolate*, v8::Handle<v8::Object> creationContext) override;
virtual v8::Handle<v8::Value> rejectedValue(v8::Isolate*, v8::Handle<v8::Object> creationContext) override;
HolderType m_holder;
ResolvedType m_resolved;
RejectedType m_rejected;
};
template<typename HolderType, typename ResolvedType, typename RejectedType>
template<typename PassHolderType>
ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::ScriptPromiseProperty(ExecutionContext* executionContext, PassHolderType holder, Name 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 (state() != Pending) {
ASSERT_NOT_REACHED();
return;
}
if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
return;
m_resolved = value;
resolveOrReject(Resolved);
}
template<typename HolderType, typename ResolvedType, typename RejectedType>
template<typename PassRejectedType>
void ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::reject(PassRejectedType value)
{
if (state() != Pending) {
ASSERT_NOT_REACHED();
return;
}
if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
return;
m_rejected = value;
resolveOrReject(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 = toV8(m_holder, creationContext, isolate);
return value.As<v8::Object>();
}
template<typename HolderType, typename ResolvedType, typename RejectedType>
v8::Handle<v8::Value> ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::resolvedValue(v8::Isolate* isolate, v8::Handle<v8::Object> creationContext)
{
ASSERT(state() == Resolved);
return toV8(m_resolved, creationContext, isolate);
}
template<typename HolderType, typename ResolvedType, typename RejectedType>
v8::Handle<v8::Value> ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::rejectedValue(v8::Isolate* isolate, v8::Handle<v8::Object> creationContext)
{
ASSERT(state() == Rejected);
return toV8(m_rejected, creationContext, isolate);
}
template<typename HolderType, typename ResolvedType, typename RejectedType>
void ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::reset()
{
resetBase();
m_resolved = ResolvedType();
m_rejected = RejectedType();
}
template<typename HolderType, typename ResolvedType, typename RejectedType>
void ScriptPromiseProperty<HolderType, ResolvedType, RejectedType>::trace(Visitor* visitor)
{
TraceIfNeeded<HolderType>::trace(visitor, &m_holder);
TraceIfNeeded<ResolvedType>::trace(visitor, &m_resolved);
TraceIfNeeded<RejectedType>::trace(visitor, &m_rejected);
ScriptPromisePropertyBase::trace(visitor);
}
} // namespace blink
#endif // ScriptPromiseProperty_h
|