/*
 * Copyright (C) 2006, 2007, 2008 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.
 */

#import "config.h"
#import "WebCoreThread.h"

#if PLATFORM(IOS)

#import "CommonVM.h"
#import "FloatingPointEnvironment.h"
#import "RuntimeApplicationChecks.h"
#import "ThreadGlobalData.h"
#import "WAKWindow.h"
#import "WebCoreThreadInternal.h"
#import "WebCoreThreadMessage.h"
#import "WebCoreThreadRun.h"
#import "WKUtilities.h"

#import <JavaScriptCore/InitializeThreading.h>
#import <JavaScriptCore/JSLock.h>
#import <wtf/Assertions.h>
#import <wtf/MainThread.h>
#import <wtf/RecursiveLockAdapter.h>
#import <wtf/RunLoop.h>
#import <wtf/Threading.h>
#import <wtf/text/AtomicString.h>

#import <Foundation/NSInvocation.h>
#import <libkern/OSAtomic.h>
#import <objc/runtime.h>

#define LOG_MESSAGES 0
#define LOG_WEB_LOCK 0
#define LOG_MAIN_THREAD_LOCKING 0
#define LOG_RELEASES 0

#define DistantFuture   (86400.0 * 2000 * 365.2425 + 86400.0)   // same as +[NSDate distantFuture]

static const constexpr Seconds DelegateWaitInterval { 10_s };

static void _WebThreadAutoLock();
static void _WebThreadLock();
static void _WebThreadLockFromAnyThread(bool shouldLog);
static void _WebThreadUnlock();

@interface NSObject(ForwardDeclarations)
-(void)_webcore_releaseOnWebThread;
-(void)_webcore_releaseWithWebThreadLock;
@end

@implementation NSObject(WebCoreThreadAdditions)

- (void)releaseOnMainThread {
    if ([NSThread isMainThread])
        [self release];
    else
        [self performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
}

@end

using NSAutoreleasePoolMark = void*;
#ifdef __cplusplus
extern "C" {
#endif
extern NSAutoreleasePoolMark NSPushAutoreleasePool(unsigned ignored);
extern void NSPopAutoreleasePool(NSAutoreleasePoolMark token);
#ifdef __cplusplus
}
#endif

static RecursiveLock webLock;
static Lock webThreadReleaseLock;
static RecursiveLock webCoreReleaseLock;

static NSAutoreleasePoolMark autoreleasePoolMark;
static CFRunLoopRef webThreadRunLoop;
static NSRunLoop* webThreadNSRunLoop;
static pthread_t webThread;
static BOOL isWebThreadLocked;
static BOOL webThreadStarted;
static unsigned webThreadLockCount;

static NSAutoreleasePoolMark savedAutoreleasePoolMark;
static BOOL isNestedWebThreadRunLoop;
typedef enum {
    PushOrPopAutoreleasePool,
    IgnoreAutoreleasePool
} AutoreleasePoolOperation;

static CFRunLoopSourceRef WebThreadReleaseSource;
static CFMutableArrayRef WebThreadReleaseObjArray;

static void MainThreadAdoptAndRelease(id obj);

static Lock delegateLock;
static StaticCondition delegateCondition;
static NSInvocation* delegateInvocation;
static CFRunLoopSourceRef delegateSource = nullptr;
static BOOL delegateHandled;
#if LOG_MAIN_THREAD_LOCKING
static BOOL sendingDelegateMessage;
#endif

static CFRunLoopObserverRef mainRunLoopAutoUnlockObserver;

static Lock startupLock;
static StaticCondition startupCondition;

static WebThreadContext* webThreadContext;
static unsigned mainThreadLockCount;
static unsigned otherThreadLockCount;
static unsigned sMainThreadModalCount;

WEBCORE_EXPORT volatile bool webThreadShouldYield;

static void WebCoreObjCDeallocOnWebThreadImpl(id self, SEL _cmd);
static void WebCoreObjCDeallocWithWebThreadLock(Class cls);
static void WebCoreObjCDeallocWithWebThreadLockImpl(id self, SEL _cmd);

static NSMutableArray* sAsyncDelegates = nil;

static inline void SendMessage(NSInvocation* invocation)
{
    [invocation invoke];
    MainThreadAdoptAndRelease(invocation);
}

static void HandleDelegateSource(void*)
{
    ASSERT(!WebThreadIsCurrent());

#if LOG_MAIN_THREAD_LOCKING
    sendingDelegateMessage = YES;
#endif

    _WebThreadAutoLock();

    {
        auto locker = holdLock(delegateLock);

#if LOG_MESSAGES
        if ([[delegateInvocation target] isKindOfClass:[NSNotificationCenter class]]) {
            id argument0;
            [delegateInvocation getArgument:&argument0 atIndex:0];
            NSLog(@"notification receive: %@", argument0);
        } else
            NSLog(@"delegate receive: %@", NSStringFromSelector([delegateInvocation selector]));
#endif

        SendMessage(delegateInvocation);

        delegateHandled = YES;
        delegateCondition.notifyOne();
    }

#if LOG_MAIN_THREAD_LOCKING
    sendingDelegateMessage = NO;
#endif
}

static void SendDelegateMessage(NSInvocation* invocation)
{
    if (!WebThreadIsCurrent()) {
        SendMessage(invocation);
        return;
    }

    ASSERT(delegateSource);
    delegateLock.lock();

    delegateInvocation = invocation;
    delegateHandled = NO;

#if LOG_MESSAGES
    if ([[delegateInvocation target] isKindOfClass:[NSNotificationCenter class]]) {
        id argument0;
        [delegateInvocation getArgument:&argument0 atIndex:0];
        NSLog(@"notification send: %@", argument0);
    } else
        NSLog(@"delegate send: %@", NSStringFromSelector([delegateInvocation selector]));
#endif

    {
        // Code block created to scope JSC::JSLock::DropAllLocks outside of WebThreadLock()
        JSC::JSLock::DropAllLocks dropAllLocks(WebCore::commonVM());
        _WebThreadUnlock();

        CFRunLoopSourceSignal(delegateSource);
        CFRunLoopWakeUp(CFRunLoopGetMain());

        while (!delegateHandled) {
            if (!delegateCondition.waitFor(delegateLock, DelegateWaitInterval)) {
                id delegateInformation;
                if ([[delegateInvocation target] isKindOfClass:[NSNotificationCenter class]])
                    [delegateInvocation getArgument:&delegateInformation atIndex:0];
                else
                    delegateInformation = NSStringFromSelector([delegateInvocation selector]);
    
                CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain());
                NSLog(@"%s: delegate (%@) failed to return after waiting %f seconds. main run loop mode: %@", __PRETTY_FUNCTION__, delegateInformation, DelegateWaitInterval.seconds(), mode);
                if (mode)
                    CFRelease(mode);
            }
        }
        delegateLock.unlock();
        _WebThreadLock();
    }
}

void WebThreadRunOnMainThread(void(^delegateBlock)())
{
    if (!WebThreadIsCurrent()) {
        ASSERT(pthread_main_np());
        delegateBlock();
        return;
    }

    JSC::JSLock::DropAllLocks dropAllLocks(WebCore::commonVM());
    _WebThreadUnlock();

    void (^delegateBlockCopy)() = Block_copy(delegateBlock);
    dispatch_sync(dispatch_get_main_queue(), delegateBlockCopy);
    Block_release(delegateBlockCopy);

    _WebThreadLock();
}

static void MainThreadAdoptAndRelease(id obj)
{
    if (!WebThreadIsEnabled() || CFRunLoopGetMain() == CFRunLoopGetCurrent()) {
        [obj release];
        return;
    }
#if LOG_RELEASES
    NSLog(@"Release send [web thread] : %@", obj);
#endif
    // We own obj at this point, so we don't need the block to implicitly
    // retain it.
    __block id objNotRetained = obj;
    dispatch_async(dispatch_get_main_queue(), ^{
        [objNotRetained release];
    });
}

void WebThreadAdoptAndRelease(id obj)
{
    ASSERT(!WebThreadIsCurrent());
    ASSERT(WebThreadReleaseSource);

#if LOG_RELEASES
    NSLog(@"Release send [main thread]: %@", obj);
#endif        

    auto locker = holdLock(webThreadReleaseLock);

    if (WebThreadReleaseObjArray == nil)
        WebThreadReleaseObjArray = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, nullptr);
    CFArrayAppendValue(WebThreadReleaseObjArray, obj);
    CFRunLoopSourceSignal(WebThreadReleaseSource);
    CFRunLoopWakeUp(webThreadRunLoop);
}

void WebCoreObjCDeallocOnWebThread(Class cls)
{
    SEL releaseSEL = @selector(release);
    SEL webThreadReleaseSEL = @selector(_webcore_releaseOnWebThread);

    // get the existing release method
    Method releaseMethod = class_getInstanceMethod(cls, releaseSEL);
    if (!releaseMethod) {
        ASSERT_WITH_MESSAGE(releaseMethod, "WebCoreObjCDeallocOnWebThread() failed to find %s for %@", releaseSEL, NSStringFromClass(cls));
        return;
    }

    // add the implementation that ensures release WebThread release/deallocation
    if (!class_addMethod(cls, webThreadReleaseSEL, (IMP)WebCoreObjCDeallocOnWebThreadImpl, method_getTypeEncoding(releaseMethod))) {
        ASSERT_WITH_MESSAGE(releaseMethod, "WebCoreObjCDeallocOnWebThread() failed to add %s for %@", webThreadReleaseSEL, NSStringFromClass(cls));
        return;
    }

    // ensure the implementation exists at cls in the class hierarchy
    if (class_addMethod(cls, releaseSEL, class_getMethodImplementation(cls, releaseSEL), method_getTypeEncoding(releaseMethod)))
        releaseMethod = class_getInstanceMethod(cls, releaseSEL);

    // swizzle the old release for the new implementation
    method_exchangeImplementations(releaseMethod, class_getInstanceMethod(cls, webThreadReleaseSEL));
}

void WebCoreObjCDeallocWithWebThreadLock(Class cls)
{
    SEL releaseSEL = @selector(release);
    SEL webThreadLockReleaseSEL = @selector(_webcore_releaseWithWebThreadLock);

    // get the existing release method
    Method releaseMethod = class_getInstanceMethod(cls, releaseSEL);
    if (!releaseMethod) {
        ASSERT_WITH_MESSAGE(releaseMethod, "WebCoreObjCDeallocWithWebThreadLock() failed to find %s for %@", releaseSEL, NSStringFromClass(cls));
        return;
    }

    // add the implementation that ensures release WebThreadLock release/deallocation
    if (!class_addMethod(cls, webThreadLockReleaseSEL, (IMP)WebCoreObjCDeallocWithWebThreadLockImpl, method_getTypeEncoding(releaseMethod))) {
        ASSERT_WITH_MESSAGE(releaseMethod, "WebCoreObjCDeallocWithWebThreadLock() failed to add %s for %@", webThreadLockReleaseSEL, NSStringFromClass(cls));
        return;
    }

    // ensure the implementation exists at cls in the class hierarchy
    if (class_addMethod(cls, releaseSEL, class_getMethodImplementation(cls, releaseSEL), method_getTypeEncoding(releaseMethod)))
        releaseMethod = class_getInstanceMethod(cls, releaseSEL);

    // swizzle the old release for the new implementation
    method_exchangeImplementations(releaseMethod, class_getInstanceMethod(cls, webThreadLockReleaseSEL));
}

void WebCoreObjCDeallocOnWebThreadImpl(id self, SEL)
{
    if (!WebThreadIsEnabled()) {
        [self _webcore_releaseOnWebThread];
        return;
    }

    {
        auto locker = holdLock(webCoreReleaseLock);
        if ([self retainCount] != 1) {
            // This is not the only reference retaining the object, so another
            // thread could also call release - hold the lock whilst calling
            // release to avoid a race condition.
            [self _webcore_releaseOnWebThread];
            return;
        }
        // This is the only reference retaining the object, so we can
        // safely release the webCoreReleaseLock now.
    }
    if (WebThreadIsCurrent())
        [self _webcore_releaseOnWebThread];
    else
        WebThreadAdoptAndRelease(self);
}

void WebCoreObjCDeallocWithWebThreadLockImpl(id self, SEL)
{
    auto locker = holdLock(webCoreReleaseLock);
    if (WebThreadIsLockedOrDisabled() || 1 != [self retainCount])
        [self _webcore_releaseWithWebThreadLock];
    else
        WebThreadAdoptAndRelease(self);
}

static void HandleWebThreadReleaseSource(void*)
{
    ASSERT(WebThreadIsCurrent());

    CFMutableArrayRef objects = nullptr;
    {
        auto locker = holdLock(webThreadReleaseLock);
        if (CFArrayGetCount(WebThreadReleaseObjArray)) {
            objects = CFArrayCreateMutableCopy(nullptr, 0, WebThreadReleaseObjArray);
            CFArrayRemoveAllValues(WebThreadReleaseObjArray);
        }
    }

    if (!objects)
        return;

    for (unsigned i = 0, count = CFArrayGetCount(objects); i < count; ++i) {
        id obj = (id)CFArrayGetValueAtIndex(objects, i);
#if LOG_RELEASES
        NSLog(@"Release recv [web thread] : %@", obj);
#endif
        [obj release];
    }

    CFRelease(objects);
}

void WebThreadCallDelegate(NSInvocation* invocation)
{
    // NSInvocation released in SendMessage()
    SendDelegateMessage([invocation retain]);
}

void WebThreadPostNotification(NSString* name, id object, id userInfo)
{
    if (pthread_main_np())
        [[NSNotificationCenter defaultCenter] postNotificationName:name object:object userInfo:userInfo];
    else {
        dispatch_async(dispatch_get_main_queue(), ^ {
            [[NSNotificationCenter defaultCenter] postNotificationName:name object:object userInfo:userInfo];
        });
    }
}

void WebThreadCallDelegateAsync(NSInvocation* invocation)
{
    ASSERT(invocation);
    if (WebThreadIsCurrent())
        [sAsyncDelegates addObject:invocation];
    else
        WebThreadCallDelegate(invocation);
}

// Note: despite the name, returns an autoreleased object.
NSInvocation* WebThreadMakeNSInvocation(id target, SEL selector)
{
    NSMethodSignature* signature = [target methodSignatureForSelector:selector];
    ASSERT(signature);
    if (signature) {
        NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
        [invocation setSelector:selector];
        [invocation setTarget:target];
        [invocation retainArguments];
        return invocation;
    }
    return nil;
}

static void MainRunLoopAutoUnlock(CFRunLoopObserverRef, CFRunLoopActivity, void*)
{
    ASSERT(!WebThreadIsCurrent());

    if (sMainThreadModalCount)
        return;
    
    CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), mainRunLoopAutoUnlockObserver, kCFRunLoopCommonModes);

    _WebThreadUnlock();
}

static void _WebThreadAutoLock(void)
{
    ASSERT(!WebThreadIsCurrent());

    if (!mainThreadLockCount) {
        CFRunLoopAddObserver(CFRunLoopGetCurrent(), mainRunLoopAutoUnlockObserver, kCFRunLoopCommonModes);    
        _WebThreadLock();
        CFRunLoopWakeUp(CFRunLoopGetMain());
    }
}

static void WebRunLoopLockInternal(AutoreleasePoolOperation poolOperation)
{
    _WebThreadLock();
    if (poolOperation == PushOrPopAutoreleasePool)
        autoreleasePoolMark = NSPushAutoreleasePool(0);
    isWebThreadLocked = YES;
}

static void WebRunLoopUnlockInternal(AutoreleasePoolOperation poolOperation)
{
    ASSERT(sAsyncDelegates);
    if ([sAsyncDelegates count]) {
        for (NSInvocation* invocation in sAsyncDelegates)
            SendDelegateMessage([invocation retain]);
        [sAsyncDelegates removeAllObjects];
    }

    if (poolOperation == PushOrPopAutoreleasePool)
        NSPopAutoreleasePool(autoreleasePoolMark);

    _WebThreadUnlock();
    isWebThreadLocked = NO;
}

static void WebRunLoopLock(CFRunLoopObserverRef, CFRunLoopActivity activity, void*)
{
    ASSERT(WebThreadIsCurrent());
    ASSERT_UNUSED(activity, activity == kCFRunLoopAfterWaiting || activity == kCFRunLoopBeforeTimers || activity == kCFRunLoopBeforeSources);

    // If the WebThread is locked by the main thread then we want to
    // grab the lock ourselves when the main thread releases the lock.
    if (isWebThreadLocked && !mainThreadLockCount)
        return;
    WebRunLoopLockInternal(PushOrPopAutoreleasePool);
}

static void WebRunLoopUnlock(CFRunLoopObserverRef, CFRunLoopActivity activity, void*)
{
    ASSERT(WebThreadIsCurrent());
    ASSERT_UNUSED(activity, activity == kCFRunLoopBeforeWaiting || activity == kCFRunLoopExit);
    ASSERT(!mainThreadLockCount);

    if (!isWebThreadLocked)
        return;
    WebRunLoopUnlockInternal(PushOrPopAutoreleasePool);
}

static void MainRunLoopUnlockGuard(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void* context)
{
    ASSERT(!WebThreadIsCurrent());

    // We shouldn't have the web lock at this point.  However, MobileMail sometimes
    // get to a state where the main thread has web lock but it didn't release it on last
    // runloop exit, and web thread gets stuck at waiting for the lock. If this happens,
    // we need to help release the lock.  See <rdar://problem/8005192>.
    if (mainThreadLockCount && !sMainThreadModalCount) {
        NSLog(@"WARNING: Main thread didn't release the lock at last runloop exit!");

        MainRunLoopAutoUnlock(observer, activity, context);
        if (mainThreadLockCount)
            mainThreadLockCount = 0;
    }
}

static void _WebRunLoopEnableNestedFromMainThread()
{
    CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), mainRunLoopAutoUnlockObserver, kCFRunLoopCommonModes);
}

static void _WebRunLoopDisableNestedFromMainThread()
{
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), mainRunLoopAutoUnlockObserver, kCFRunLoopCommonModes); 
}

void WebRunLoopEnableNested()
{
    if (!WebThreadIsEnabled())
        return;

    ASSERT(!isNestedWebThreadRunLoop);

    if (!WebThreadIsCurrent())
        _WebRunLoopEnableNestedFromMainThread();

    savedAutoreleasePoolMark = autoreleasePoolMark;
    autoreleasePoolMark = 0;
    WebRunLoopUnlockInternal(IgnoreAutoreleasePool);
    isNestedWebThreadRunLoop = YES;
}

void WebRunLoopDisableNested()
{
    if (!WebThreadIsEnabled())
        return;

    ASSERT(isNestedWebThreadRunLoop);

    if (!WebThreadIsCurrent())
        _WebRunLoopDisableNestedFromMainThread();

    autoreleasePoolMark = savedAutoreleasePoolMark;
    savedAutoreleasePoolMark = 0;
    WebRunLoopLockInternal(IgnoreAutoreleasePool);
    isNestedWebThreadRunLoop = NO;
}

static ThreadSpecific<WebThreadContext, WTF::CanBeGCThread::True>* threadContext;
static WebThreadContext* CurrentThreadContext()
{
    static std::once_flag flag;
    std::call_once(flag, [] {
        threadContext = new ThreadSpecific<WebThreadContext, WTF::CanBeGCThread::True>();
    });
    return *threadContext;
}

static void* RunWebThread(void*)
{
    FloatingPointEnvironment::singleton().propagateMainThreadEnvironment();

    // WTF::initializeMainThread() needs to be called before JSC::initializeThreading() since the
    // code invoked by the latter needs to know if it's running on the WebThread. See
    // <rdar://problem/8502487>.
    WTF::initializeMainThread();
    WTF::initializeWebThread();
    JSC::initializeThreading();
    
    // Make sure that the WebThread and the main thread share the same ThreadGlobalData objects.
    WebCore::threadGlobalData().setWebCoreThreadData();

#if HAVE(PTHREAD_SETNAME_NP)
    pthread_setname_np("WebThread");
#endif

    webThreadContext = CurrentThreadContext();
    webThreadRunLoop = CFRunLoopGetCurrent();
    webThreadNSRunLoop = [[NSRunLoop currentRunLoop] retain];

    CFRunLoopObserverRef webRunLoopLockObserverRef = CFRunLoopObserverCreate(nullptr, kCFRunLoopBeforeTimers | kCFRunLoopBeforeSources | kCFRunLoopAfterWaiting, YES, 0, WebRunLoopLock, nullptr);
    CFRunLoopAddObserver(webThreadRunLoop, webRunLoopLockObserverRef, kCFRunLoopCommonModes);
    CFRelease(webRunLoopLockObserverRef);
    
    WebThreadInitRunQueue();

    // We must have the lock when CA paints in the web thread. CA commits at 2000000 so we use larger order number than that to free the lock.
    CFRunLoopObserverRef webRunLoopUnlockObserverRef = CFRunLoopObserverCreate(nullptr, kCFRunLoopBeforeWaiting | kCFRunLoopExit, YES, 2500000, WebRunLoopUnlock, nullptr);    
    CFRunLoopAddObserver(webThreadRunLoop, webRunLoopUnlockObserverRef, kCFRunLoopCommonModes);
    CFRelease(webRunLoopUnlockObserverRef);    

    CFRunLoopSourceContext ReleaseSourceContext = {0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, HandleWebThreadReleaseSource};
    WebThreadReleaseSource = CFRunLoopSourceCreate(nullptr, -1, &ReleaseSourceContext);
    CFRunLoopAddSource(webThreadRunLoop, WebThreadReleaseSource, kCFRunLoopDefaultMode);

    {
        LockHolder locker(startupLock);
        startupCondition.notifyOne();
    }

    while (1)
        CFRunLoopRunInMode(kCFRunLoopDefaultMode, DistantFuture, true);

    return nullptr;
}

static void StartWebThread()
{
    webThreadStarted = TRUE;

    // ThreadGlobalData touches AtomicString, which requires Threading initialization.
    WTF::initializeThreading();

    // Initialize AtomicString on the main thread.
    WTF::AtomicString::init();

    // Initialize ThreadGlobalData on the main UI thread so that the WebCore thread
    // can later set it's thread-specific data to point to the same objects.
    WebCore::ThreadGlobalData& unused = WebCore::threadGlobalData();
    UNUSED_PARAM(unused);

    RunLoop::initializeMainRunLoop();

    // register class for WebThread deallocation
    WebCoreObjCDeallocOnWebThread([WAKWindow class]);
    WebCoreObjCDeallocWithWebThreadLock([WAKView class]);

    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    CFRunLoopSourceContext delegateSourceContext = {0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, HandleDelegateSource};
    delegateSource = CFRunLoopSourceCreate(nullptr, 0, &delegateSourceContext);

    // We shouldn't get delegate callbacks while scrolling, but there might be
    // one outstanding when we start.  Add the source for all common run loop
    // modes so we don't block the web thread while scrolling.
    CFRunLoopAddSource(runLoop, delegateSource, kCFRunLoopCommonModes);

    sAsyncDelegates = [[NSMutableArray alloc] init];

    mainRunLoopAutoUnlockObserver = CFRunLoopObserverCreate(nullptr, kCFRunLoopBeforeWaiting | kCFRunLoopExit, YES, 3000001, MainRunLoopAutoUnlock, nullptr);

    pthread_attr_t tattr;
    pthread_attr_init(&tattr);
    pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM);
    // The web thread is a secondary thread, and secondary threads are usually given
    // a 512 kb stack, but we need more space in order to have room for the JavaScriptCore
    // reentrancy limit. This limit works on both the simulator and the device.
    pthread_attr_setstacksize(&tattr, 200 * 4096);

    struct sched_param param;
    pthread_attr_getschedparam(&tattr, &param);
    param.sched_priority--;
    pthread_attr_setschedparam(&tattr, &param);

    // Wait for the web thread to startup completely before we continue.
    {
        LockHolder locker(startupLock);

        // Propagate the mainThread's fenv to workers & the web thread.
        FloatingPointEnvironment::singleton().saveMainThreadEnvironment();

        pthread_create(&webThread, &tattr, RunWebThread, nullptr);
        pthread_attr_destroy(&tattr);

        startupCondition.wait(startupLock);
    }

    initializeApplicationUIThread();
}

#if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
static unsigned lockCount;
#endif

static void _WebThreadLock()
{
    // Suspend the web thread if the main thread is trying to lock.
    bool onMainThread = pthread_main_np();
    if (onMainThread)
        webThreadShouldYield = true;
    else if (!WebThreadIsCurrent()) {
        NSLog(@"%s, %p: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...", __PRETTY_FUNCTION__, CurrentThreadContext());
        CRASH();
    }

    webLock.lock();

#if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
    lockCount++;
#if LOG_WEB_LOCK
    NSLog(@"lock   %d, web-thread: %d", lockCount, WebThreadIsCurrent());
#endif
#endif
    if (onMainThread) {
        ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
        webThreadShouldYield = false;
        mainThreadLockCount++;
#if LOG_MAIN_THREAD_LOCKING
        if (!sendingDelegateMessage && lockCount == 1)
            NSLog(@"Main thread locking outside of delegate messages.");
#endif
    } else {
        webThreadLockCount++;
        if (webThreadLockCount > 1) {
            NSLog(@"%s, %p: Multiple locks on web thread not allowed! Please file a bug. Crashing now...", __PRETTY_FUNCTION__, CurrentThreadContext());
            CRASH();
        }
    }
}

void WebThreadLock(void)
{
    if (!webThreadStarted || pthread_equal(webThread, pthread_self()))
        return;
    _WebThreadAutoLock();
}

void WebThreadUnlock(void)
{
    // This is a no-op, we unlock automatically on top of the runloop
    ASSERT(!WebThreadIsCurrent());
}

void WebThreadLockFromAnyThread(void)
{
    _WebThreadLockFromAnyThread(true);
}
    
void WebThreadLockFromAnyThreadNoLog(void)
{
    _WebThreadLockFromAnyThread(false);
}

static void _WebThreadLockFromAnyThread(bool shouldLog)
{
    if (!webThreadStarted)
        return;
    ASSERT(!WebThreadIsCurrent());
    if (pthread_main_np()) {
        _WebThreadAutoLock();
        return;
    }
    if (shouldLog)
        NSLog(@"%s, %p: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread.", __PRETTY_FUNCTION__, CurrentThreadContext());

    webLock.lock();

    // This used for any thread other than the web thread.
    otherThreadLockCount++;
    webThreadShouldYield = false;
}

void WebThreadUnlockFromAnyThread(void)
{
    if (!webThreadStarted)
        return;
    ASSERT(!WebThreadIsCurrent());
    // No-op except from a secondary thread.
    if (pthread_main_np())
        return;
    
    ASSERT(otherThreadLockCount);
    otherThreadLockCount--;

    webLock.unlock();
}

void WebThreadUnlockGuardForMail(void)
{
    ASSERT(!WebThreadIsCurrent());

    CFRunLoopObserverRef mainRunLoopUnlockGuardObserver = CFRunLoopObserverCreate(nullptr, kCFRunLoopEntry, YES, 0, MainRunLoopUnlockGuard, nullptr);
    CFRunLoopAddObserver(CFRunLoopGetMain(), mainRunLoopUnlockGuardObserver, kCFRunLoopCommonModes);
    CFRelease(mainRunLoopUnlockGuardObserver);
}

void _WebThreadUnlock()
{
#if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
    lockCount--;
#if LOG_WEB_LOCK
    NSLog(@"unlock %d, web-thread: %d", lockCount, WebThreadIsCurrent());
#endif
#endif
    
    if (!WebThreadIsCurrent()) {
        ASSERT(mainThreadLockCount);
        mainThreadLockCount--;
    } else {    
        webThreadLockCount--;
        webThreadShouldYield = false;
    }

    webLock.unlock();
}

bool WebThreadIsLocked(void)
{
    if (WebThreadIsCurrent())
        return webThreadLockCount;

    if (pthread_main_np())
        return mainThreadLockCount;

    return otherThreadLockCount;
}

bool WebThreadIsLockedOrDisabled(void)
{
    return !WebThreadIsEnabled() || WebThreadIsLocked();
}

void WebThreadLockPushModal(void)
{
    if (WebThreadIsCurrent())
        return;
    
    ASSERT(WebThreadIsLocked());
    ++sMainThreadModalCount;
}

void WebThreadLockPopModal(void)
{
    if (WebThreadIsCurrent())
        return;
    
    ASSERT(WebThreadIsLocked());
    ASSERT(sMainThreadModalCount);
    --sMainThreadModalCount;
}

CFRunLoopRef WebThreadRunLoop(void)
{
    if (webThreadStarted) {
        ASSERT(webThreadRunLoop);
        return webThreadRunLoop;
    }
    
    return CFRunLoopGetCurrent();
}

NSRunLoop* WebThreadNSRunLoop(void)
{
    if (webThreadStarted) {
        ASSERT(webThreadNSRunLoop);
        return webThreadNSRunLoop;
    }

    return [NSRunLoop currentRunLoop];
}

WebThreadContext* WebThreadCurrentContext(void)
{
    return CurrentThreadContext();
}

void WebThreadEnable(void)
{
    RELEASE_ASSERT_WITH_MESSAGE(!WebCore::IOSApplication::isWebProcess(), "The WebProcess should never run a Web Thread");

    static std::once_flag flag;
    std::call_once(flag, StartWebThread);
}

bool WebThreadIsEnabled(void)
{
    return webThreadStarted;
}

bool WebThreadIsCurrent(void)
{
    return webThreadStarted && pthread_equal(webThread, pthread_self());
}

bool WebThreadNotCurrent(void)
{
    return webThreadStarted && !pthread_equal(webThread, pthread_self());
}

#endif // PLATFORM(IOS)
