dbc30e353480940534bd21318726d4ead6872d7e
[WebKit-https.git] / Source / WebCore / bindings / js / JSMainThreadExecState.h
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #pragma once
28
29 #include "CustomElementReactionQueue.h"
30 #include "JSDOMBinding.h"
31 #include <runtime/Completion.h>
32 #include <runtime/Microtask.h>
33 #include <wtf/MainThread.h>
34
35 namespace WebCore {
36
37 class InspectorInstrumentationCookie;
38 class ScriptExecutionContext;
39
40 class JSMainThreadExecState {
41     WTF_MAKE_NONCOPYABLE(JSMainThreadExecState);
42     friend class JSMainThreadNullState;
43 public:
44     static JSC::ExecState* currentState()
45     {
46         ASSERT(isMainThread());
47         return s_mainThreadState;
48     };
49     
50     static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)
51     {
52         JSMainThreadExecState currentState(exec);
53         return JSC::call(exec, functionObject, callType, callData, thisValue, args, returnedException);
54     };
55
56     static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
57     {
58         JSMainThreadExecState currentState(exec);
59         return JSC::evaluate(exec, source, thisValue, returnedException);
60     };
61
62     static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
63     {
64         NakedPtr<JSC::Exception> unused;
65         return evaluate(exec, source, thisValue, unused);
66     };
67
68     static JSC::JSValue profiledCall(JSC::ExecState* exec, JSC::ProfilingReason reason, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)
69     {
70         JSMainThreadExecState currentState(exec);
71         return JSC::profiledCall(exec, reason, functionObject, callType, callData, thisValue, args, returnedException);
72     }
73
74     static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
75     {
76         JSMainThreadExecState currentState(exec);
77         return JSC::profiledEvaluate(exec, reason, source, thisValue, returnedException);
78     }
79
80     static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
81     {
82         NakedPtr<JSC::Exception> unused;
83         return profiledEvaluate(exec, reason, source, thisValue, unused);
84     }
85
86     static void runTask(JSC::ExecState* exec, JSC::Microtask& task)
87     {
88         JSMainThreadExecState currentState(exec);
89         task.run(exec);
90     }
91
92     static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue scriptFetcher)
93     {
94         JSMainThreadExecState currentState(&state);
95         return *JSC::loadModule(&state, moduleName, scriptFetcher);
96     }
97
98     static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher)
99     {
100         JSMainThreadExecState currentState(&state);
101         return *JSC::loadModule(&state, sourceCode, scriptFetcher);
102     }
103
104     static JSC::JSValue linkAndEvaluateModule(JSC::ExecState& state, const JSC::Identifier& moduleKey, JSC::JSValue scriptFetcher, NakedPtr<JSC::Exception>& returnedException)
105     {
106         JSC::VM& vm = state.vm();
107         auto scope = DECLARE_CATCH_SCOPE(vm);
108     
109         JSMainThreadExecState currentState(&state);
110         auto returnValue = JSC::linkAndEvaluateModule(&state, moduleKey, scriptFetcher);
111         if (UNLIKELY(scope.exception())) {
112             returnedException = scope.exception();
113             scope.clearException();
114             return JSC::jsUndefined();
115         }
116         return returnValue;
117     }
118
119     static InspectorInstrumentationCookie instrumentFunctionCall(ScriptExecutionContext*, JSC::CallType, const JSC::CallData&);
120     static InspectorInstrumentationCookie instrumentFunctionConstruct(ScriptExecutionContext*, JSC::ConstructType, const JSC::ConstructData&);
121
122 private:
123     explicit JSMainThreadExecState(JSC::ExecState* exec)
124         : m_previousState(s_mainThreadState)
125         , m_lock(exec)
126     {
127         ASSERT(isMainThread());
128         s_mainThreadState = exec;
129     };
130
131     ~JSMainThreadExecState()
132     {
133         JSC::VM& vm = s_mainThreadState->vm();
134         auto scope = DECLARE_CATCH_SCOPE(vm);
135         ASSERT(isMainThread());
136         scope.assertNoException();
137
138         JSC::ExecState* state = s_mainThreadState;
139         bool didExitJavaScript = s_mainThreadState && !m_previousState;
140
141         s_mainThreadState = m_previousState;
142
143         if (didExitJavaScript)
144             didLeaveScriptContext(state);
145     }
146
147     template<typename Type, Type jsType, typename DataType> static InspectorInstrumentationCookie instrumentFunctionInternal(ScriptExecutionContext*, Type, const DataType&);
148
149     WEBCORE_EXPORT static JSC::ExecState* s_mainThreadState;
150     JSC::ExecState* m_previousState;
151     JSC::JSLockHolder m_lock;
152
153     static void didLeaveScriptContext(JSC::ExecState*);
154 };
155
156 // Null state prevents origin security checks.
157 // Used by non-JavaScript bindings (ObjC, GObject).
158 class JSMainThreadNullState {
159     WTF_MAKE_NONCOPYABLE(JSMainThreadNullState);
160 public:
161     explicit JSMainThreadNullState()
162         : m_previousState(JSMainThreadExecState::s_mainThreadState)
163     {
164         ASSERT(isMainThread());
165         JSMainThreadExecState::s_mainThreadState = nullptr;
166     }
167
168     ~JSMainThreadNullState()
169     {
170         ASSERT(isMainThread());
171         JSMainThreadExecState::s_mainThreadState = m_previousState;
172     }
173
174 private:
175     JSC::ExecState* m_previousState;
176     CustomElementReactionStack m_customElementReactionStack;
177 };
178
179 JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException);
180 JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException);
181
182 } // namespace WebCore