• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "bindings/core/v8/ScriptPromise.h"
33 
34 #include "bindings/core/v8/ExceptionMessages.h"
35 #include "bindings/core/v8/ExceptionState.h"
36 #include "bindings/core/v8/V8Binding.h"
37 #include "bindings/core/v8/V8ThrowException.h"
38 #include "core/dom/DOMException.h"
39 
40 #include <v8.h>
41 
42 namespace blink {
43 
44 namespace {
45 
46 struct WithScriptState {
47     // Used by ToV8Value<WithScriptState, ScriptState*>.
getCreationContextblink::__anon905e2b670111::WithScriptState48     static v8::Handle<v8::Object> getCreationContext(ScriptState* scriptState)
49     {
50         return scriptState->context()->Global();
51     }
52 };
53 
54 } // namespace
55 
InternalResolver(ScriptState * scriptState)56 ScriptPromise::InternalResolver::InternalResolver(ScriptState* scriptState)
57     : m_resolver(scriptState, v8::Promise::Resolver::New(scriptState->isolate())) { }
58 
v8Promise() const59 v8::Local<v8::Promise> ScriptPromise::InternalResolver::v8Promise() const
60 {
61     if (m_resolver.isEmpty())
62         return v8::Local<v8::Promise>();
63     return m_resolver.v8Value().As<v8::Promise::Resolver>()->GetPromise();
64 }
65 
promise() const66 ScriptPromise ScriptPromise::InternalResolver::promise() const
67 {
68     if (m_resolver.isEmpty())
69         return ScriptPromise();
70     return ScriptPromise(m_resolver.scriptState(), v8Promise());
71 }
72 
resolve(v8::Local<v8::Value> value)73 void ScriptPromise::InternalResolver::resolve(v8::Local<v8::Value> value)
74 {
75     if (m_resolver.isEmpty())
76         return;
77     m_resolver.v8Value().As<v8::Promise::Resolver>()->Resolve(value);
78     clear();
79 }
80 
reject(v8::Local<v8::Value> value)81 void ScriptPromise::InternalResolver::reject(v8::Local<v8::Value> value)
82 {
83     if (m_resolver.isEmpty())
84         return;
85     m_resolver.v8Value().As<v8::Promise::Resolver>()->Reject(value);
86     clear();
87 }
88 
ScriptPromise(ScriptState * scriptState,v8::Handle<v8::Value> value)89 ScriptPromise::ScriptPromise(ScriptState* scriptState, v8::Handle<v8::Value> value)
90     : m_scriptState(scriptState)
91 {
92     if (value.IsEmpty())
93         return;
94 
95     if (!value->IsPromise()) {
96         m_promise = ScriptValue(scriptState, v8::Handle<v8::Value>());
97         V8ThrowException::throwTypeError("the given value is not a Promise", scriptState->isolate());
98         return;
99     }
100     m_promise = ScriptValue(scriptState, value);
101 }
102 
then(v8::Handle<v8::Function> onFulfilled,v8::Handle<v8::Function> onRejected)103 ScriptPromise ScriptPromise::then(v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected)
104 {
105     if (m_promise.isEmpty())
106         return ScriptPromise();
107 
108     v8::Local<v8::Object> promise = m_promise.v8Value().As<v8::Object>();
109 
110     ASSERT(promise->IsPromise());
111     // Return this Promise if no handlers are given.
112     // In fact it is not the exact bahavior of Promise.prototype.then
113     // but that is not a problem in this case.
114     v8::Local<v8::Promise> resultPromise = promise.As<v8::Promise>();
115     if (!onFulfilled.IsEmpty()) {
116         resultPromise = resultPromise->Then(onFulfilled);
117         if (resultPromise.IsEmpty()) {
118             // v8::Promise::Then may return an empty value, for example when
119             // the stack is exhausted.
120             return ScriptPromise();
121         }
122     }
123     if (!onRejected.IsEmpty())
124         resultPromise = resultPromise->Catch(onRejected);
125 
126     return ScriptPromise(m_scriptState.get(), resultPromise);
127 }
128 
cast(ScriptState * scriptState,const ScriptValue & value)129 ScriptPromise ScriptPromise::cast(ScriptState* scriptState, const ScriptValue& value)
130 {
131     return ScriptPromise::cast(scriptState, value.v8Value());
132 }
133 
cast(ScriptState * scriptState,v8::Handle<v8::Value> value)134 ScriptPromise ScriptPromise::cast(ScriptState* scriptState, v8::Handle<v8::Value> value)
135 {
136     if (value.IsEmpty())
137         return ScriptPromise();
138     if (value->IsPromise()) {
139         return ScriptPromise(scriptState, value);
140     }
141     InternalResolver resolver(scriptState);
142     ScriptPromise promise = resolver.promise();
143     resolver.resolve(value);
144     return promise;
145 }
146 
reject(ScriptState * scriptState,const ScriptValue & value)147 ScriptPromise ScriptPromise::reject(ScriptState* scriptState, const ScriptValue& value)
148 {
149     return ScriptPromise::reject(scriptState, value.v8Value());
150 }
151 
reject(ScriptState * scriptState,v8::Handle<v8::Value> value)152 ScriptPromise ScriptPromise::reject(ScriptState* scriptState, v8::Handle<v8::Value> value)
153 {
154     if (value.IsEmpty())
155         return ScriptPromise();
156     InternalResolver resolver(scriptState);
157     ScriptPromise promise = resolver.promise();
158     resolver.reject(value);
159     return promise;
160 }
161 
rejectWithDOMException(ScriptState * scriptState,PassRefPtrWillBeRawPtr<DOMException> exception)162 ScriptPromise ScriptPromise::rejectWithDOMException(ScriptState* scriptState, PassRefPtrWillBeRawPtr<DOMException> exception)
163 {
164     ASSERT(scriptState->isolate()->InContext());
165     return reject(scriptState, V8ValueTraits<PassRefPtrWillBeRawPtr<DOMException> >::toV8Value(exception, scriptState->context()->Global(), scriptState->isolate()));
166 }
167 
rejectRaw(v8::Isolate * isolate,v8::Handle<v8::Value> value)168 v8::Local<v8::Promise> ScriptPromise::rejectRaw(v8::Isolate* isolate, v8::Handle<v8::Value> value)
169 {
170     if (value.IsEmpty())
171         return v8::Local<v8::Promise>();
172     v8::Local<v8::Promise::Resolver> resolver = v8::Promise::Resolver::New(isolate);
173     v8::Local<v8::Promise> promise = resolver->GetPromise();
174     resolver->Reject(value);
175     return promise;
176 }
177 
178 } // namespace blink
179