15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
35267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
31bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include "config.h"
32197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ScriptPromise.h"
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
34e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "bindings/core/v8/ExceptionMessages.h"
35e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "bindings/core/v8/ExceptionState.h"
36197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/V8Binding.h"
37e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)#include "bindings/core/v8/V8ThrowException.h"
38d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/dom/DOMException.h"
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)#include <v8.h>
41926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
42c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
44d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)namespace {
45d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
46d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)struct WithScriptState {
47d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // Used by ToV8Value<WithScriptState, ScriptState*>.
48d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    static v8::Handle<v8::Object> getCreationContext(ScriptState* scriptState)
49d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    {
50d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return scriptState->context()->Global();
51d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
52d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)};
53d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
54d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} // namespace
55d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
56197021e6b966cfb06891637935ef33fff06433d1Ben MurdochScriptPromise::InternalResolver::InternalResolver(ScriptState* scriptState)
57197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    : m_resolver(scriptState, v8::Promise::Resolver::New(scriptState->isolate())) { }
58197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
59197021e6b966cfb06891637935ef33fff06433d1Ben Murdochv8::Local<v8::Promise> ScriptPromise::InternalResolver::v8Promise() const
60197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
61197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_resolver.isEmpty())
62197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return v8::Local<v8::Promise>();
63197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return m_resolver.v8Value().As<v8::Promise::Resolver>()->GetPromise();
64197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
65197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
66197021e6b966cfb06891637935ef33fff06433d1Ben MurdochScriptPromise ScriptPromise::InternalResolver::promise() const
67197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
68197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_resolver.isEmpty())
69197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return ScriptPromise();
70197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return ScriptPromise(m_resolver.scriptState(), v8Promise());
71197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
72197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
73197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid ScriptPromise::InternalResolver::resolve(v8::Local<v8::Value> value)
74197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_resolver.isEmpty())
76197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return;
77197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_resolver.v8Value().As<v8::Promise::Resolver>()->Resolve(value);
78197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    clear();
79197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
80197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
81197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid ScriptPromise::InternalResolver::reject(v8::Local<v8::Value> value)
82197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch{
83197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (m_resolver.isEmpty())
84197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        return;
85197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    m_resolver.v8Value().As<v8::Promise::Resolver>()->Reject(value);
86197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    clear();
87197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch}
88197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
89323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)ScriptPromise::ScriptPromise(ScriptState* scriptState, v8::Handle<v8::Value> value)
90323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    : m_scriptState(scriptState)
91d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
9243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    if (value.IsEmpty())
9343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        return;
9443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
95d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (!value->IsPromise()) {
96323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        m_promise = ScriptValue(scriptState, v8::Handle<v8::Value>());
97323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        V8ThrowException::throwTypeError("the given value is not a Promise", scriptState->isolate());
98d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return;
99d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    }
100323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    m_promise = ScriptValue(scriptState, value);
101d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
102d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciScriptPromise ScriptPromise::then(v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected)
10409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
10510f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (m_promise.isEmpty())
10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return ScriptPromise();
10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
10843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    v8::Local<v8::Object> promise = m_promise.v8Value().As<v8::Object>();
10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
11043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    ASSERT(promise->IsPromise());
11143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // Return this Promise if no handlers are given.
11243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // In fact it is not the exact bahavior of Promise.prototype.then
11343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    // but that is not a problem in this case.
11443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    v8::Local<v8::Promise> resultPromise = promise.As<v8::Promise>();
1157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!onFulfilled.IsEmpty()) {
1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        resultPromise = resultPromise->Then(onFulfilled);
11743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        if (resultPromise.IsEmpty()) {
1185d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)            // v8::Promise::Then may return an empty value, for example when
11943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)            // the stack is exhausted.
12043e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)            return ScriptPromise();
12143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)        }
12243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)    }
1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!onRejected.IsEmpty())
1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        resultPromise = resultPromise->Catch(onRejected);
12543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
126323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    return ScriptPromise(m_scriptState.get(), resultPromise);
1275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
1285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
1295d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)ScriptPromise ScriptPromise::cast(ScriptState* scriptState, const ScriptValue& value)
130bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles){
1315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return ScriptPromise::cast(scriptState, value.v8Value());
132d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
133d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
134d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)ScriptPromise ScriptPromise::cast(ScriptState* scriptState, v8::Handle<v8::Value> value)
135d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
136d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (value.IsEmpty())
137d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        return ScriptPromise();
138d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (value->IsPromise()) {
139d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return ScriptPromise(scriptState, value);
14010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    }
141197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    InternalResolver resolver(scriptState);
142197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ScriptPromise promise = resolver.promise();
143197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    resolver.resolve(value);
144d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return promise;
145d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
146d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
1475d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)ScriptPromise ScriptPromise::reject(ScriptState* scriptState, const ScriptValue& value)
148d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
1495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    return ScriptPromise::reject(scriptState, value.v8Value());
150d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
151d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
152d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)ScriptPromise ScriptPromise::reject(ScriptState* scriptState, v8::Handle<v8::Value> value)
153d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
154d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (value.IsEmpty())
155d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        return ScriptPromise();
156197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    InternalResolver resolver(scriptState);
157197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    ScriptPromise promise = resolver.promise();
158197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    resolver.reject(value);
159d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    return promise;
160d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}
161d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
162d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)ScriptPromise ScriptPromise::rejectWithDOMException(ScriptState* scriptState, PassRefPtrWillBeRawPtr<DOMException> exception)
163d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){
164d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    ASSERT(scriptState->isolate()->InContext());
165197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    return reject(scriptState, V8ValueTraits<PassRefPtrWillBeRawPtr<DOMException> >::toV8Value(exception, scriptState->context()->Global(), scriptState->isolate()));
166bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)}
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
168e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)v8::Local<v8::Promise> ScriptPromise::rejectRaw(v8::Isolate* isolate, v8::Handle<v8::Value> value)
169e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles){
170e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    if (value.IsEmpty())
171e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        return v8::Local<v8::Promise>();
172e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    v8::Local<v8::Promise::Resolver> resolver = v8::Promise::Resolver::New(isolate);
173e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    v8::Local<v8::Promise> promise = resolver->GetPromise();
174e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    resolver->Reject(value);
175e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    return promise;
176e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
177e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)
178c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
179