1/*
2 * Copyright (C) 2010 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
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#ifndef JSMainThreadExecState_h
27#define JSMainThreadExecState_h
28
29#include "JSDOMBinding.h"
30#include <runtime/Completion.h>
31#include <runtime/Microtask.h>
32#include <wtf/MainThread.h>
33
34#if PLATFORM(IOS)
35#include "WebCoreThread.h"
36#endif
37
38namespace WebCore {
39
40class InspectorInstrumentationCookie;
41class ScriptExecutionContext;
42
43class JSMainThreadExecState {
44    WTF_MAKE_NONCOPYABLE(JSMainThreadExecState);
45    friend class JSMainThreadNullState;
46public:
47    static JSC::ExecState* currentState()
48    {
49        ASSERT(isMainThread());
50        return s_mainThreadState;
51    };
52
53    static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, JSC::JSValue* exception)
54    {
55        JSMainThreadExecState currentState(exec);
56        return JSC::call(exec, functionObject, callType, callData, thisValue, args, exception);
57    };
58
59    static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, JSC::JSValue* exception)
60    {
61        JSMainThreadExecState currentState(exec);
62        return JSC::evaluate(exec, source, thisValue, exception);
63    };
64
65    static void runTask(JSC::ExecState* exec, JSC::Microtask& task)
66    {
67        JSMainThreadExecState currentState(exec);
68        task.run(exec);
69    }
70
71    static InspectorInstrumentationCookie instrumentFunctionCall(ScriptExecutionContext*, JSC::CallType, const JSC::CallData&);
72
73private:
74    explicit JSMainThreadExecState(JSC::ExecState* exec)
75        : m_previousState(s_mainThreadState)
76        , m_lock(exec)
77    {
78        ASSERT(isMainThread());
79        s_mainThreadState = exec;
80    };
81
82    ~JSMainThreadExecState()
83    {
84        ASSERT(isMainThread());
85        ASSERT(!s_mainThreadState->hadException());
86
87        bool didExitJavaScript = s_mainThreadState && !m_previousState;
88
89        s_mainThreadState = m_previousState;
90
91        if (didExitJavaScript)
92            didLeaveScriptContext();
93    }
94
95    static JSC::ExecState* s_mainThreadState;
96    JSC::ExecState* m_previousState;
97    JSC::JSLockHolder m_lock;
98
99    static void didLeaveScriptContext();
100};
101
102// Null state prevents origin security checks.
103// Used by non-JavaScript bindings (ObjC, GObject).
104class JSMainThreadNullState {
105    WTF_MAKE_NONCOPYABLE(JSMainThreadNullState);
106public:
107    explicit JSMainThreadNullState()
108        : m_previousState(JSMainThreadExecState::s_mainThreadState)
109    {
110        ASSERT(isMainThread());
111        JSMainThreadExecState::s_mainThreadState = nullptr;
112    }
113
114    ~JSMainThreadNullState()
115    {
116        ASSERT(isMainThread());
117        JSMainThreadExecState::s_mainThreadState = m_previousState;
118    }
119
120private:
121    JSC::ExecState* m_previousState;
122};
123
124JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList& args, JSC::JSValue* exception);
125JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, JSC::JSValue* exception);
126
127} // namespace WebCore
128
129#endif // JSMainThreadExecState_h
130