#pragma once #include "root.h" #include #include #include #include #include #include #include "CachedScript.h" #include "wtf/URL.h" namespace WebCore { class ScriptExecutionContext : public CanMakeWeakPtr { public: ScriptExecutionContext(JSC::VM* vm, JSC::JSGlobalObject* globalObject) : m_vm(vm) , m_globalObject(globalObject) { } class Task { WTF_MAKE_FAST_ALLOCATED; public: enum CleanupTaskTag { CleanupTask }; template::value && std::is_convertible>::value>::type> Task(T task) : m_task(WTFMove(task)) , m_isCleanupTask(false) { } Task(Function&& task) : m_task([task = WTFMove(task)](ScriptExecutionContext&) { task(); }) , m_isCleanupTask(false) { } template>::value>::type> Task(CleanupTaskTag, T task) : m_task(WTFMove(task)) , m_isCleanupTask(true) { } void performTask(ScriptExecutionContext& context) { m_task(context); } bool isCleanupTask() const { return m_isCleanupTask; } protected: Function m_task; bool m_isCleanupTask; }; JSC::JSGlobalObject* jsGlobalObject() { return m_globalObject; } const WTF::URL& url() const { return m_url; } bool activeDOMObjectsAreSuspended() { return false; } bool activeDOMObjectsAreStopped() { return false; } bool isContextThread() { return true; } bool isDocument() { return false; } bool isWorkerGlobalScope() { return true; } bool isJSExecutionForbidden() { return false; } EventLoopTaskGroup& eventLoop() { return m_eventLoop; } void reportException(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL, JSC::Exception* exception, RefPtr&&, CachedScript* = nullptr, bool = false) { } void reportUnhandledPromiseRejection(JSC::JSGlobalObject&, JSC::JSPromise&, RefPtr&&) { } // Called from the constructor and destructors of ActiveDOMObject. void didCreateActiveDOMObject(ActiveDOMObject&); void willDestroyActiveDOMObject(ActiveDOMObject&); // Called after the construction of an ActiveDOMObject to synchronize suspend state. void suspendActiveDOMObjectIfNeeded(ActiveDOMObject&); void didCreateDestructionObserver(ContextDestructionObserver&); void willDestroyDestructionObserver(ContextDestructionObserver&); // MessagePort is conceptually a kind of ActiveDOMObject, but it needs to be tracked separately for message dispatch. void processMessageWithMessagePortsSoon(); void dispatchMessagePortEvents(); void createdMessagePort(MessagePort&); void destroyedMessagePort(MessagePort&); ReasonForSuspension reasonForSuspendingActiveDOMObjects() const { return m_reasonForSuspendingActiveDOMObjects; } bool hasPendingActivity() const; void removeFromContextsMap(); void removeRejectedPromiseTracker(); void regenerateIdentifier(); void postTask(Task&&) { } // Executes the task on context's thread asynchronously. template void postCrossThreadTask(Arguments&&... arguments) { postTask([crossThreadTask = createCrossThreadTask(arguments...)](ScriptExecutionContext&) mutable { crossThreadTask.performTask(); }); } JSC::VM& vm() { return *m_vm; } private: JSC::VM* m_vm = nullptr; JSC::JSGlobalObject* m_globalObject = nullptr; WTF::URL m_url = WTF::URL(); enum class ShouldContinue { No, Yes }; void forEachActiveDOMObject(const Function&) const; RejectedPromiseTracker& ensureRejectedPromiseTrackerSlow(); HashSet m_messagePorts; HashSet m_destructionObservers; HashSet m_activeDOMObjects; std::unique_ptr m_rejectedPromiseTracker; ReasonForSuspension m_reasonForSuspendingActiveDOMObjects { static_cast(-1) }; bool m_activeDOMObjectsAreSuspended { false }; bool m_activeDOMObjectsAreStopped { false }; bool m_inDispatchErrorEvent { false }; mutable bool m_activeDOMObjectAdditionForbidden { false }; bool m_willprocessMessageWithMessagePortsSoon { false }; }; }