189 lines
7.8 KiB
C++
189 lines
7.8 KiB
C++
/*
|
|
* Copyright (C) 2010 Google Inc. All rights reserved.
|
|
* Copyright (C) 2016-2017 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "CustomElementReactionQueue.h"
|
|
#include "JSDOMBinding.h"
|
|
#include "ThreadGlobalData.h"
|
|
#include <JavaScriptCore/CatchScope.h>
|
|
#include <JavaScriptCore/Completion.h>
|
|
#include <JavaScriptCore/Microtask.h>
|
|
#include <wtf/ForbidHeapAllocation.h>
|
|
#include <wtf/MainThread.h>
|
|
|
|
namespace WebCore {
|
|
|
|
class ScriptExecutionContext;
|
|
|
|
class JSExecState {
|
|
WTF_MAKE_NONCOPYABLE(JSExecState);
|
|
WTF_FORBID_HEAP_ALLOCATION;
|
|
friend class JSMainThreadNullState;
|
|
public:
|
|
static JSC::JSGlobalObject* currentState()
|
|
{
|
|
return threadGlobalData().currentState();
|
|
};
|
|
|
|
static JSC::JSValue call(JSC::JSGlobalObject* lexicalGlobalObject, JSC::JSValue functionObject, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)
|
|
{
|
|
JSExecState currentState(lexicalGlobalObject);
|
|
return JSC::call(lexicalGlobalObject, functionObject, callData, thisValue, args, returnedException);
|
|
};
|
|
|
|
static JSC::JSValue evaluate(JSC::JSGlobalObject* lexicalGlobalObject, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
|
|
{
|
|
JSExecState currentState(lexicalGlobalObject);
|
|
return JSC::evaluate(lexicalGlobalObject, source, thisValue, returnedException);
|
|
};
|
|
|
|
static JSC::JSValue evaluate(JSC::JSGlobalObject* lexicalGlobalObject, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
|
|
{
|
|
NakedPtr<JSC::Exception> unused;
|
|
return evaluate(lexicalGlobalObject, source, thisValue, unused);
|
|
};
|
|
|
|
static JSC::JSValue profiledCall(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ProfilingReason reason, JSC::JSValue functionObject, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)
|
|
{
|
|
JSExecState currentState(lexicalGlobalObject);
|
|
return JSC::profiledCall(lexicalGlobalObject, reason, functionObject, callData, thisValue, args, returnedException);
|
|
}
|
|
|
|
static JSC::JSValue profiledEvaluate(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
|
|
{
|
|
JSExecState currentState(lexicalGlobalObject);
|
|
return JSC::profiledEvaluate(lexicalGlobalObject, reason, source, thisValue, returnedException);
|
|
}
|
|
|
|
static JSC::JSValue profiledEvaluate(JSC::JSGlobalObject* lexicalGlobalObject, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
|
|
{
|
|
NakedPtr<JSC::Exception> unused;
|
|
return profiledEvaluate(lexicalGlobalObject, reason, source, thisValue, unused);
|
|
}
|
|
|
|
static void runTask(JSC::JSGlobalObject* lexicalGlobalObject, JSC::Microtask& task)
|
|
{
|
|
JSExecState currentState(lexicalGlobalObject);
|
|
task.run(lexicalGlobalObject);
|
|
}
|
|
|
|
static JSC::JSInternalPromise& loadModule(JSC::JSGlobalObject& lexicalGlobalObject, const String& moduleName, JSC::JSValue parameters, JSC::JSValue scriptFetcher)
|
|
{
|
|
JSExecState currentState(&lexicalGlobalObject);
|
|
return *JSC::loadModule(&lexicalGlobalObject, moduleName, parameters, scriptFetcher);
|
|
}
|
|
|
|
static JSC::JSInternalPromise& loadModule(JSC::JSGlobalObject& lexicalGlobalObject, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher)
|
|
{
|
|
JSExecState currentState(&lexicalGlobalObject);
|
|
return *JSC::loadModule(&lexicalGlobalObject, sourceCode, scriptFetcher);
|
|
}
|
|
|
|
static JSC::JSValue linkAndEvaluateModule(JSC::JSGlobalObject& lexicalGlobalObject, const JSC::Identifier& moduleKey, JSC::JSValue scriptFetcher, NakedPtr<JSC::Exception>& returnedException)
|
|
{
|
|
JSC::VM& vm = JSC::getVM(&lexicalGlobalObject);
|
|
auto scope = DECLARE_CATCH_SCOPE(vm);
|
|
|
|
JSExecState currentState(&lexicalGlobalObject);
|
|
auto returnValue = JSC::linkAndEvaluateModule(&lexicalGlobalObject, moduleKey, scriptFetcher);
|
|
if (UNLIKELY(scope.exception())) {
|
|
returnedException = scope.exception();
|
|
scope.clearException();
|
|
return JSC::jsUndefined();
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
static void instrumentFunction(ScriptExecutionContext*, const JSC::CallData&);
|
|
|
|
private:
|
|
explicit JSExecState(JSC::JSGlobalObject* lexicalGlobalObject)
|
|
: m_previousState(currentState())
|
|
, m_lock(lexicalGlobalObject)
|
|
{
|
|
setCurrentState(lexicalGlobalObject);
|
|
};
|
|
|
|
~JSExecState()
|
|
{
|
|
JSC::VM& vm = currentState()->vm();
|
|
auto scope = DECLARE_CATCH_SCOPE(vm);
|
|
scope.assertNoException();
|
|
|
|
JSC::JSGlobalObject* lexicalGlobalObject = currentState();
|
|
bool didExitJavaScript = lexicalGlobalObject && !m_previousState;
|
|
|
|
setCurrentState(m_previousState);
|
|
|
|
if (didExitJavaScript) {
|
|
didLeaveScriptContext(lexicalGlobalObject);
|
|
// We need to clear any exceptions from microtask drain.
|
|
scope.clearException();
|
|
}
|
|
}
|
|
|
|
static void setCurrentState(JSC::JSGlobalObject* lexicalGlobalObject)
|
|
{
|
|
threadGlobalData().setCurrentState(lexicalGlobalObject);
|
|
}
|
|
|
|
JSC::JSGlobalObject* m_previousState;
|
|
JSC::JSLockHolder m_lock;
|
|
|
|
static void didLeaveScriptContext(JSC::JSGlobalObject*);
|
|
};
|
|
|
|
// Null lexicalGlobalObject prevents origin security checks.
|
|
// Used by non-JavaScript bindings (ObjC, GObject).
|
|
class JSMainThreadNullState {
|
|
WTF_MAKE_NONCOPYABLE(JSMainThreadNullState);
|
|
WTF_FORBID_HEAP_ALLOCATION;
|
|
public:
|
|
explicit JSMainThreadNullState()
|
|
: m_previousState(JSExecState::currentState())
|
|
, m_customElementReactionStack(m_previousState)
|
|
{
|
|
ASSERT(isMainThread());
|
|
JSExecState::setCurrentState(nullptr);
|
|
}
|
|
|
|
~JSMainThreadNullState()
|
|
{
|
|
ASSERT(isMainThread());
|
|
JSExecState::setCurrentState(m_previousState);
|
|
}
|
|
|
|
private:
|
|
JSC::JSGlobalObject* m_previousState;
|
|
CustomElementReactionStack m_customElementReactionStack;
|
|
};
|
|
|
|
JSC::JSValue functionCallHandlerFromAnyThread(JSC::JSGlobalObject*, JSC::JSValue functionObject, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException);
|
|
JSC::JSValue evaluateHandlerFromAnyThread(JSC::JSGlobalObject*, const JSC::SourceCode&, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException);
|
|
|
|
} // namespace WebCore
|