c09ea15d93865f456c977cee5eb65222b3a89aea
[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/CatchScope.h>
32 #include <runtime/Completion.h>
33 #include <runtime/Microtask.h>
34 #include <wtf/MainThread.h>
35
36 namespace WebCore {
37
38 class InspectorInstrumentationCookie;
39 class ScriptExecutionContext;
40
41 class JSMainThreadExecState {
42     WTF_MAKE_NONCOPYABLE(JSMainThreadExecState);
43     friend class JSMainThreadNullState;
44 public:
45     static JSC::ExecState* currentState()
46     {
47         ASSERT(isMainThread());
48         return s_mainThreadState;
49     };
50     
51     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)
52     {
53         JSMainThreadExecState currentState(exec);
54         return JSC::call(exec, functionObject, callType, callData, thisValue, args, returnedException);
55     };
56
57     static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
58     {
59         JSMainThreadExecState currentState(exec);
60         return JSC::evaluate(exec, source, thisValue, returnedException);
61     };
62
63     static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
64     {
65         NakedPtr<JSC::Exception> unused;
66         return evaluate(exec, source, thisValue, unused);
67     };
68
69     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)
70     {
71         JSMainThreadExecState currentState(exec);
72         return JSC::profiledCall(exec, reason, functionObject, callType, callData, thisValue, args, returnedException);
73     }
74
75     static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
76     {
77         JSMainThreadExecState currentState(exec);
78         return JSC::profiledEvaluate(exec, reason, source, thisValue, returnedException);
79     }
80
81     static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
82     {
83         NakedPtr<JSC::Exception> unused;
84         return profiledEvaluate(exec, reason, source, thisValue, unused);
85     }
86
87     static void runTask(JSC::ExecState* exec, JSC::Microtask& task)
88     {
89         JSMainThreadExecState currentState(exec);
90         task.run(exec);
91     }
92
93     static void loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue parameters, JSC::JSValue scriptFetcher)
94     {
95         JSMainThreadExecState currentState(&state);
96         JSC::loadModule(&state, moduleName, parameters, scriptFetcher);
97     }
98
99     static void loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher)
100     {
101         JSMainThreadExecState currentState(&state);
102         JSC::loadModule(&state, sourceCode, scriptFetcher);
103     }
104
105     static JSC::JSValue linkAndEvaluateModule(JSC::ExecState& state, const JSC::Identifier& moduleKey, JSC::JSValue scriptFetcher, NakedPtr<JSC::Exception>& returnedException)
106     {
107         JSC::VM& vm = state.vm();
108         auto scope = DECLARE_CATCH_SCOPE(vm);
109     
110         JSMainThreadExecState currentState(&state);
111         auto returnValue = JSC::linkAndEvaluateModule(&state, moduleKey, scriptFetcher);
112         if (UNLIKELY(scope.exception())) {
113             returnedException = scope.exception();
114             scope.clearException();
115             return JSC::jsUndefined();
116         }
117         return returnValue;
118     }
119
120     static InspectorInstrumentationCookie instrumentFunctionCall(ScriptExecutionContext*, JSC::CallType, const JSC::CallData&);
121     static InspectorInstrumentationCookie instrumentFunctionConstruct(ScriptExecutionContext*, JSC::ConstructType, const JSC::ConstructData&);
122
123 private:
124     explicit JSMainThreadExecState(JSC::ExecState* exec)
125         : m_previousState(s_mainThreadState)
126         , m_lock(exec)
127     {
128         ASSERT(isMainThread());
129         s_mainThreadState = exec;
130     };
131
132     ~JSMainThreadExecState()
133     {
134         JSC::VM& vm = s_mainThreadState->vm();
135         auto scope = DECLARE_CATCH_SCOPE(vm);
136         ASSERT(isMainThread());
137         scope.assertNoException();
138
139         JSC::ExecState* state = s_mainThreadState;
140         bool didExitJavaScript = s_mainThreadState && !m_previousState;
141
142         s_mainThreadState = m_previousState;
143
144         if (didExitJavaScript)
145             didLeaveScriptContext(state);
146     }
147
148     template<typename Type, Type jsType, typename DataType> static InspectorInstrumentationCookie instrumentFunctionInternal(ScriptExecutionContext*, Type, const DataType&);
149
150     WEBCORE_EXPORT static JSC::ExecState* s_mainThreadState;
151     JSC::ExecState* m_previousState;
152     JSC::JSLockHolder m_lock;
153
154     static void didLeaveScriptContext(JSC::ExecState*);
155 };
156
157 // Null state prevents origin security checks.
158 // Used by non-JavaScript bindings (ObjC, GObject).
159 class JSMainThreadNullState {
160     WTF_MAKE_NONCOPYABLE(JSMainThreadNullState);
161 public:
162     explicit JSMainThreadNullState()
163         : m_previousState(JSMainThreadExecState::s_mainThreadState)
164     {
165         ASSERT(isMainThread());
166         JSMainThreadExecState::s_mainThreadState = nullptr;
167     }
168
169     ~JSMainThreadNullState()
170     {
171         ASSERT(isMainThread());
172         JSMainThreadExecState::s_mainThreadState = m_previousState;
173     }
174
175 private:
176     JSC::ExecState* m_previousState;
177     CustomElementReactionStack m_customElementReactionStack;
178 };
179
180 JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException);
181 JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException);
182
183 } // namespace WebCore