1 | /* |
2 | * Copyright (C) 2017 Apple 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 |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
14 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
15 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
18 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
19 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
20 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
21 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
22 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
23 | * THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | #include "JSDOMPromise.h" |
28 | |
29 | #include "DOMWindow.h" |
30 | #include "JSDOMWindow.h" |
31 | #include <JavaScriptCore/BuiltinNames.h> |
32 | #include <JavaScriptCore/CatchScope.h> |
33 | #include <JavaScriptCore/Exception.h> |
34 | #include <JavaScriptCore/JSNativeStdFunction.h> |
35 | #include <JavaScriptCore/JSPromiseConstructor.h> |
36 | |
37 | using namespace JSC; |
38 | |
39 | namespace WebCore { |
40 | |
41 | static inline JSC::JSValue callFunction(JSC::ExecState& state, JSC::JSValue jsFunction, JSC::JSValue thisValue, const JSC::ArgList& arguments) |
42 | { |
43 | VM& vm = state.vm(); |
44 | auto scope = DECLARE_THROW_SCOPE(vm); |
45 | JSC::CallData callData; |
46 | auto callType = JSC::getCallData(vm, jsFunction, callData); |
47 | ASSERT(callType != JSC::CallType::None); |
48 | auto result = call(&state, jsFunction, callType, callData, thisValue, arguments); |
49 | |
50 | EXCEPTION_ASSERT_UNUSED(scope, !scope.exception() || isTerminatedExecutionException(state.vm(), scope.exception())); |
51 | |
52 | return result; |
53 | } |
54 | |
55 | void DOMPromise::whenSettled(std::function<void()>&& callback) |
56 | { |
57 | whenPromiseIsSettled(globalObject(), promise(), WTFMove(callback)); |
58 | } |
59 | |
60 | void DOMPromise::whenPromiseIsSettled(JSDOMGlobalObject* globalObject, JSC::JSObject* promise, std::function<void()>&& callback) |
61 | { |
62 | auto& state = *globalObject->globalExec(); |
63 | auto& vm = state.vm(); |
64 | JSLockHolder lock(vm); |
65 | auto* handler = JSC::JSNativeStdFunction::create(vm, globalObject, 1, String { }, [callback = WTFMove(callback)] (ExecState*) mutable { |
66 | callback(); |
67 | return JSC::JSValue::encode(JSC::jsUndefined()); |
68 | }); |
69 | |
70 | const JSC::Identifier& privateName = vm.propertyNames->builtinNames().thenPrivateName(); |
71 | auto thenFunction = promise->get(&state, privateName); |
72 | ASSERT(thenFunction.isFunction(vm)); |
73 | |
74 | JSC::MarkedArgumentBuffer arguments; |
75 | arguments.append(handler); |
76 | arguments.append(handler); |
77 | callFunction(state, thenFunction, promise, arguments); |
78 | } |
79 | |
80 | JSC::JSValue DOMPromise::result() const |
81 | { |
82 | return promise()->result(m_globalObject->globalExec()->vm()); |
83 | } |
84 | |
85 | DOMPromise::Status DOMPromise::status() const |
86 | { |
87 | switch (promise()->status(m_globalObject->globalExec()->vm())) { |
88 | case JSC::JSPromise::Status::Pending: |
89 | return Status::Pending; |
90 | case JSC::JSPromise::Status::Fulfilled: |
91 | return Status::Fulfilled; |
92 | case JSC::JSPromise::Status::Rejected: |
93 | return Status::Rejected; |
94 | }; |
95 | ASSERT_NOT_REACHED(); |
96 | return Status::Rejected; |
97 | } |
98 | |
99 | } |
100 | |