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 "config.h" | |
6 #include "bindings/core/v8/ScriptPromisePropertyBase.h" | |
7 | |
8 #include "bindings/core/v8/V8Binding.h" | |
9 #include "bindings/core/v8/V8HiddenValue.h" | |
10 #include "core/dom/ExecutionContext.h" | |
11 | |
12 namespace WebCore { | |
13 | |
14 ScriptPromisePropertyBase::ScriptPromisePropertyBase(ExecutionContext* execution Context, Name name) | |
15 : ContextLifecycleObserver(executionContext) | |
16 , m_isolate(toIsolate(executionContext)) | |
17 , m_name(name) | |
18 , m_state(Pending) | |
19 { | |
20 } | |
21 | |
22 ScriptPromisePropertyBase::~ScriptPromisePropertyBase() | |
23 { | |
24 v8::HandleScope handleScope(m_isolate); | |
25 v8::Handle<v8::Object> wrapper = m_mainWorldWrapper.newLocal(m_isolate); | |
26 if (!wrapper.IsEmpty()) { | |
27 wrapper->DeleteHiddenValue(resolverName()); | |
28 wrapper->DeleteHiddenValue(promiseName()); | |
29 } | |
30 } | |
31 | |
32 static void clearHandle(const v8::WeakCallbackData<v8::Object, ScopedPersistent< v8::Object> >& data) | |
33 { | |
34 data.GetParameter()->clear(); | |
35 } | |
36 | |
37 ScriptPromise ScriptPromisePropertyBase::promise(DOMWrapperWorld& world) | |
38 { | |
39 if (!executionContext()) | |
40 return ScriptPromise(); | |
41 | |
42 if (!world.isMainWorld()) { | |
43 // FIXME: Support isolated worlds. | |
44 return ScriptPromise(); | |
45 } | |
46 | |
47 v8::HandleScope handleScope(m_isolate); | |
48 v8::Handle<v8::Context> context = toV8Context(executionContext(), world); | |
49 if (context.IsEmpty()) | |
50 return ScriptPromise(); | |
51 ScriptState* scriptState = ScriptState::from(context); | |
52 ScriptState::Scope scope(scriptState); | |
53 | |
54 v8::Handle<v8::Object> wrapper = m_mainWorldWrapper.newLocal(m_isolate); | |
55 if (wrapper.IsEmpty()) { | |
56 wrapper = holder(context->Global(), m_isolate); | |
57 ASSERT(!wrapper.IsEmpty()); | |
58 ASSERT(V8HiddenValue::getHiddenValue(m_isolate, wrapper, resolverName()) .IsEmpty()); | |
59 ASSERT(V8HiddenValue::getHiddenValue(m_isolate, wrapper, promiseName()). IsEmpty()); | |
60 m_mainWorldWrapper.set(m_isolate, wrapper); | |
61 m_mainWorldWrapper.setWeak(&m_mainWorldWrapper, &clearHandle); | |
62 } | |
63 ASSERT(wrapper->CreationContext() == context); | |
64 | |
65 v8::Handle<v8::Promise> promise = V8HiddenValue::getHiddenValue(m_isolate, w rapper, promiseName()).As<v8::Promise>(); | |
66 if (!promise.IsEmpty()) { | |
67 // Return cached Promise | |
68 return ScriptPromise(scriptState, promise); | |
69 } | |
70 | |
71 // Create and cache the Promise | |
72 v8::Handle<v8::Promise::Resolver> resolver = v8::Promise::Resolver::New(m_is olate); | |
73 promise = resolver->GetPromise(); | |
74 V8HiddenValue::setHiddenValue(m_isolate, wrapper, promiseName(), promise); | |
75 V8HiddenValue::setHiddenValue(m_isolate, promise, promiseName(), wrapper); | |
haraken
2014/07/03 02:43:20
Just help me understand: Why do you need the refer
| |
76 | |
77 switch (m_state) { | |
78 case Pending: | |
79 // Cache the resolver too | |
80 V8HiddenValue::setHiddenValue(m_isolate, wrapper, resolverName(), resolv er); | |
81 break; | |
82 case Resolved: | |
83 case Rejected: | |
84 resolveOrRejectInternal(resolver); | |
85 break; | |
86 } | |
87 | |
88 return ScriptPromise(scriptState, promise); | |
89 } | |
90 | |
91 void ScriptPromisePropertyBase::resolveOrReject(State targetState) | |
92 { | |
93 ASSERT(executionContext()); | |
94 ASSERT(m_state == Pending); | |
95 ASSERT(targetState == Resolved || targetState == Rejected); | |
96 | |
97 m_state = targetState; | |
98 | |
99 v8::HandleScope handleScope(m_isolate); | |
100 v8::Handle<v8::Object> wrapper = m_mainWorldWrapper.newLocal(m_isolate); | |
101 if (wrapper.IsEmpty()) | |
102 return; // wrapper has died or was never populated | |
103 ScriptState::Scope scope(ScriptState::from(wrapper->CreationContext())); | |
104 | |
105 v8::Handle<v8::Promise::Resolver> resolver = V8HiddenValue::getHiddenValue(m _isolate, wrapper, resolverName()).As<v8::Promise::Resolver>(); | |
106 | |
107 V8HiddenValue::deleteHiddenValue(m_isolate, wrapper, resolverName()); | |
108 resolveOrRejectInternal(resolver); | |
109 } | |
110 | |
111 void ScriptPromisePropertyBase::resolveOrRejectInternal(v8::Handle<v8::Promise:: Resolver> resolver) | |
112 { | |
113 switch (m_state) { | |
114 case Pending: | |
115 ASSERT_NOT_REACHED(); | |
116 break; | |
117 case Resolved: | |
118 resolver->Resolve(resolvedValue(resolver->CreationContext()->Global(), m _isolate)); | |
119 break; | |
120 case Rejected: | |
121 resolver->Reject(rejectedValue(resolver->CreationContext()->Global(), m_ isolate)); | |
122 break; | |
123 } | |
124 } | |
125 | |
126 v8::Handle<v8::String> ScriptPromisePropertyBase::promiseName() | |
haraken
2014/07/03 02:43:20
I'd move this to V8HiddenValue.cpp.
| |
127 { | |
128 switch (m_name) { | |
129 #define P(Name) \ | |
130 case Name: \ | |
131 return V8HiddenValue::Name ## Promise(m_isolate); | |
132 | |
133 SCRIPT_PROMISE_PROPERTIES(P) | |
134 | |
135 #undef P | |
136 } | |
137 ASSERT_NOT_REACHED(); | |
138 return v8::Handle<v8::String>(); | |
139 } | |
140 | |
141 v8::Handle<v8::String> ScriptPromisePropertyBase::resolverName() | |
142 { | |
143 switch (m_name) { | |
144 #define P(Name) \ | |
145 case Name: \ | |
146 return V8HiddenValue::Name ## Resolver(m_isolate); | |
147 | |
148 SCRIPT_PROMISE_PROPERTIES(P) | |
149 | |
150 #undef P | |
151 } | |
152 ASSERT_NOT_REACHED(); | |
153 return v8::Handle<v8::String>(); | |
154 } | |
155 | |
156 } // namespace WebCore | |
OLD | NEW |