| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "sky/engine/config.h" | |
| 6 #include "sky/engine/bindings/core/v8/ScriptPromisePropertyBase.h" | |
| 7 | |
| 8 #include "sky/engine/bindings/core/v8/ScopedPersistent.h" | |
| 9 #include "sky/engine/bindings/core/v8/ScriptState.h" | |
| 10 #include "sky/engine/bindings/core/v8/V8Binding.h" | |
| 11 #include "sky/engine/bindings/core/v8/V8HiddenValue.h" | |
| 12 #include "sky/engine/core/dom/ExecutionContext.h" | |
| 13 | |
| 14 namespace blink { | |
| 15 | |
| 16 ScriptPromisePropertyBase::ScriptPromisePropertyBase(ExecutionContext* execution
Context, Name name) | |
| 17 : ContextLifecycleObserver(executionContext) | |
| 18 , m_isolate(toIsolate(executionContext)) | |
| 19 , m_name(name) | |
| 20 , m_state(Pending) | |
| 21 { | |
| 22 } | |
| 23 | |
| 24 ScriptPromisePropertyBase::~ScriptPromisePropertyBase() | |
| 25 { | |
| 26 clearWrappers(); | |
| 27 } | |
| 28 | |
| 29 static void clearHandle(const v8::WeakCallbackData<v8::Object, ScopedPersistent<
v8::Object> >& data) | |
| 30 { | |
| 31 data.GetParameter()->clear(); | |
| 32 } | |
| 33 | |
| 34 ScriptPromise ScriptPromisePropertyBase::promise(DOMWrapperWorld& world) | |
| 35 { | |
| 36 if (!executionContext()) | |
| 37 return ScriptPromise(); | |
| 38 | |
| 39 v8::HandleScope handleScope(m_isolate); | |
| 40 v8::Handle<v8::Context> context = toV8Context(executionContext(), world); | |
| 41 if (context.IsEmpty()) | |
| 42 return ScriptPromise(); | |
| 43 ScriptState* scriptState = ScriptState::from(context); | |
| 44 ScriptState::Scope scope(scriptState); | |
| 45 | |
| 46 v8::Handle<v8::Object> wrapper = ensureHolderWrapper(scriptState); | |
| 47 ASSERT(wrapper->CreationContext() == context); | |
| 48 | |
| 49 v8::Handle<v8::Value> cachedPromise = V8HiddenValue::getHiddenValue(m_isolat
e, wrapper, promiseName()); | |
| 50 if (!cachedPromise.IsEmpty()) | |
| 51 return ScriptPromise(scriptState, cachedPromise); | |
| 52 | |
| 53 // Create and cache the Promise | |
| 54 v8::Handle<v8::Promise::Resolver> resolver = v8::Promise::Resolver::New(m_is
olate); | |
| 55 v8::Handle<v8::Promise> promise = resolver->GetPromise(); | |
| 56 V8HiddenValue::setHiddenValue(m_isolate, wrapper, promiseName(), promise); | |
| 57 | |
| 58 switch (m_state) { | |
| 59 case Pending: | |
| 60 // Cache the resolver too | |
| 61 V8HiddenValue::setHiddenValue(m_isolate, wrapper, resolverName(), resolv
er); | |
| 62 break; | |
| 63 case Resolved: | |
| 64 case Rejected: | |
| 65 resolveOrRejectInternal(resolver); | |
| 66 break; | |
| 67 } | |
| 68 | |
| 69 return ScriptPromise(scriptState, promise); | |
| 70 } | |
| 71 | |
| 72 void ScriptPromisePropertyBase::resolveOrReject(State targetState) | |
| 73 { | |
| 74 ASSERT(executionContext()); | |
| 75 ASSERT(m_state == Pending); | |
| 76 ASSERT(targetState == Resolved || targetState == Rejected); | |
| 77 | |
| 78 m_state = targetState; | |
| 79 | |
| 80 v8::HandleScope handleScope(m_isolate); | |
| 81 size_t i = 0; | |
| 82 while (i < m_wrappers.size()) { | |
| 83 const OwnPtr<ScopedPersistent<v8::Object> >& persistent = m_wrappers[i]; | |
| 84 if (persistent->isEmpty()) { | |
| 85 // wrapper has died. | |
| 86 // Since v8 GC can run during the iteration and clear the reference, | |
| 87 // we can't move this check out of the loop. | |
| 88 m_wrappers.remove(i); | |
| 89 continue; | |
| 90 } | |
| 91 v8::Local<v8::Object> wrapper = persistent->newLocal(m_isolate); | |
| 92 ScriptState::Scope scope(ScriptState::from(wrapper->CreationContext())); | |
| 93 | |
| 94 v8::Local<v8::Promise::Resolver> resolver = V8HiddenValue::getHiddenValu
e(m_isolate, wrapper, resolverName()).As<v8::Promise::Resolver>(); | |
| 95 | |
| 96 V8HiddenValue::deleteHiddenValue(m_isolate, wrapper, resolverName()); | |
| 97 resolveOrRejectInternal(resolver); | |
| 98 ++i; | |
| 99 } | |
| 100 } | |
| 101 | |
| 102 void ScriptPromisePropertyBase::resetBase() | |
| 103 { | |
| 104 clearWrappers(); | |
| 105 m_state = Pending; | |
| 106 } | |
| 107 | |
| 108 void ScriptPromisePropertyBase::resolveOrRejectInternal(v8::Handle<v8::Promise::
Resolver> resolver) | |
| 109 { | |
| 110 switch (m_state) { | |
| 111 case Pending: | |
| 112 ASSERT_NOT_REACHED(); | |
| 113 break; | |
| 114 case Resolved: | |
| 115 resolver->Resolve(resolvedValue(resolver->CreationContext()->Global(), m
_isolate)); | |
| 116 break; | |
| 117 case Rejected: | |
| 118 resolver->Reject(rejectedValue(resolver->CreationContext()->Global(), m_
isolate)); | |
| 119 break; | |
| 120 } | |
| 121 } | |
| 122 | |
| 123 v8::Local<v8::Object> ScriptPromisePropertyBase::ensureHolderWrapper(ScriptState
* scriptState) | |
| 124 { | |
| 125 v8::Local<v8::Context> context = scriptState->context(); | |
| 126 size_t i = 0; | |
| 127 while (i < m_wrappers.size()) { | |
| 128 const OwnPtr<ScopedPersistent<v8::Object> >& persistent = m_wrappers[i]; | |
| 129 if (persistent->isEmpty()) { | |
| 130 // wrapper has died. | |
| 131 // Since v8 GC can run during the iteration and clear the reference, | |
| 132 // we can't move this check out of the loop. | |
| 133 m_wrappers.remove(i); | |
| 134 continue; | |
| 135 } | |
| 136 | |
| 137 v8::Local<v8::Object> wrapper = persistent->newLocal(m_isolate); | |
| 138 if (wrapper->CreationContext() == context) | |
| 139 return wrapper; | |
| 140 ++i; | |
| 141 } | |
| 142 v8::Local<v8::Object> wrapper = holder(context->Global(), m_isolate); | |
| 143 OwnPtr<ScopedPersistent<v8::Object> > weakPersistent = adoptPtr(new ScopedPe
rsistent<v8::Object>); | |
| 144 weakPersistent->set(m_isolate, wrapper); | |
| 145 weakPersistent->setWeak(weakPersistent.get(), &clearHandle); | |
| 146 m_wrappers.append(weakPersistent.release()); | |
| 147 return wrapper; | |
| 148 } | |
| 149 | |
| 150 void ScriptPromisePropertyBase::clearWrappers() | |
| 151 { | |
| 152 v8::HandleScope handleScope(m_isolate); | |
| 153 for (WeakPersistentSet::iterator i = m_wrappers.begin(); i != m_wrappers.end
(); ++i) { | |
| 154 v8::Local<v8::Object> wrapper = (*i)->newLocal(m_isolate); | |
| 155 if (!wrapper.IsEmpty()) { | |
| 156 wrapper->DeleteHiddenValue(resolverName()); | |
| 157 wrapper->DeleteHiddenValue(promiseName()); | |
| 158 } | |
| 159 } | |
| 160 m_wrappers.clear(); | |
| 161 } | |
| 162 | |
| 163 v8::Handle<v8::String> ScriptPromisePropertyBase::promiseName() | |
| 164 { | |
| 165 switch (m_name) { | |
| 166 #define P(Name) \ | |
| 167 case Name: \ | |
| 168 return V8HiddenValue::Name ## Promise(m_isolate); | |
| 169 | |
| 170 SCRIPT_PROMISE_PROPERTIES(P) | |
| 171 | |
| 172 #undef P | |
| 173 } | |
| 174 ASSERT_NOT_REACHED(); | |
| 175 return v8::Handle<v8::String>(); | |
| 176 } | |
| 177 | |
| 178 v8::Handle<v8::String> ScriptPromisePropertyBase::resolverName() | |
| 179 { | |
| 180 switch (m_name) { | |
| 181 #define P(Name) \ | |
| 182 case Name: \ | |
| 183 return V8HiddenValue::Name ## Resolver(m_isolate); | |
| 184 | |
| 185 SCRIPT_PROMISE_PROPERTIES(P) | |
| 186 | |
| 187 #undef P | |
| 188 } | |
| 189 ASSERT_NOT_REACHED(); | |
| 190 return v8::Handle<v8::String>(); | |
| 191 } | |
| 192 | |
| 193 } // namespace blink | |
| OLD | NEW |