diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts
index 144fed737..59b09ecf3 100644
--- a/Runtime/src/index.ts
+++ b/Runtime/src/index.ts
@@ -4,6 +4,8 @@ interface ExportedMemory {
 
 type ref = number;
 type pointer = number;
+// Function invocation call, using a host function ID and array of parameters
+type function_call = [number, any[]];
 
 interface GlobalVariable {}
 declare const window: GlobalVariable;
@@ -22,6 +24,7 @@ if (typeof globalThis !== "undefined") {
 interface SwiftRuntimeExportedFunctions {
     swjs_library_version(): number;
     swjs_prepare_host_function_call(size: number): pointer;
+    swjs_allocate_asyncify_buffer(size: number): pointer;
     swjs_cleanup_host_function_call(argv: pointer): void;
     swjs_call_host_function(
         host_func_id: number,
@@ -31,6 +34,29 @@ interface SwiftRuntimeExportedFunctions {
     ): void;
 }
 
+/**
+ * Optional methods exposed by Wasm modules after running an `asyncify` pass,
+ * e.g. `wasm-opt -asyncify`.
+ * More details at [Pause and Resume WebAssembly with Binaryen's Asyncify](https://kripken.github.io/blog/wasm/2019/07/16/asyncify.html).
+*/
+interface AsyncifyExportedFunctions {
+    asyncify_start_rewind(stack: pointer): void;
+    asyncify_stop_rewind(): void;
+    asyncify_start_unwind(stack: pointer): void;
+    asyncify_stop_unwind(): void;
+}
+
+/**
+ * Runtime check if Wasm module exposes asyncify methods
+*/
+function isAsyncified(exports: any): exports is AsyncifyExportedFunctions {
+    const asyncifiedExports = exports as AsyncifyExportedFunctions;
+    return asyncifiedExports.asyncify_start_rewind !== undefined &&
+        asyncifiedExports.asyncify_stop_rewind !== undefined &&
+        asyncifiedExports.asyncify_start_unwind !== undefined &&
+        asyncifiedExports.asyncify_stop_unwind !== undefined;
+}
+
 enum JavaScriptValueKind {
     Invalid = -1,
     Boolean = 0,
@@ -115,23 +141,61 @@ class SwiftRuntimeHeap {
     }
 }
 
+// Helper methods for asyncify
+const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
+
 export class SwiftRuntime {
     private instance: WebAssembly.Instance | null;
     private heap: SwiftRuntimeHeap;
     private version: number = 701;
 
+    // Support Asyncified modules
+    private isSleeping: boolean;
+    private instanceIsAsyncified: boolean;
+    private resumeCallback: () => void;
+    private asyncifyBufferPointer: pointer | null;
+    // Keeps track of function calls requested while instance is sleeping
+    private pendingHostFunctionCalls: function_call[];
+
     constructor() {
         this.instance = null;
         this.heap = new SwiftRuntimeHeap();
+        this.isSleeping = false;
+        this.instanceIsAsyncified = false;
+        this.resumeCallback = () => { };
+        this.asyncifyBufferPointer = null;
+        this.pendingHostFunctionCalls = [];
     }
 
-    setInstance(instance: WebAssembly.Instance) {
+    /**
+     * Set the Wasm instance
+     * @param instance The instantiate Wasm instance
+     * @param resumeCallback Optional callback for resuming instance after
+     * unwinding and rewinding stack (for asyncified modules).
+     */
+    setInstance(instance: WebAssembly.Instance, resumeCallback?: () => void) {
         this.instance = instance;
+        if (resumeCallback) {
+            this.resumeCallback = resumeCallback;
+        }
         const exports = (this.instance
             .exports as any) as SwiftRuntimeExportedFunctions;
         if (exports.swjs_library_version() != this.version) {
             throw new Error("The versions of JavaScriptKit are incompatible.");
         }
+        this.instanceIsAsyncified = isAsyncified(exports);
+    }
+
+    /**
+    * Report that the module has been started.
+    * Required for asyncified Wasm modules, so runtime has a chance to call required methods.
+    **/
+    didStart() {
+        if (this.instance && this.instanceIsAsyncified) {
+            const asyncifyExports = (this.instance
+                .exports as any) as AsyncifyExportedFunctions;
+            asyncifyExports.asyncify_stop_unwind();
+        }
     }
 
     importObjects() {
@@ -144,6 +208,10 @@ export class SwiftRuntime {
         const callHostFunction = (host_func_id: number, args: any[]) => {
             if (!this.instance)
                 throw new Error("WebAssembly instance is not set yet");
+            if (this.isSleeping) {
+                this.pendingHostFunctionCalls.push([host_func_id, args]);
+                return;
+            }
             const exports = (this.instance
                 .exports as any) as SwiftRuntimeExportedFunctions;
             const argc = args.length;
@@ -328,6 +396,54 @@ export class SwiftRuntime {
             return result;
         };
 
+        const syncAwait = (
+            promise: Promise<any>,
+            kind_ptr?: pointer,
+            payload1_ptr?: pointer,
+            payload2_ptr?: pointer
+        ) => {
+            if (!this.instance || !this.instanceIsAsyncified) {
+                throw new Error("Calling async methods requires preprocessing Wasm module with `--asyncify`");
+            }
+            const exports = (this.instance.exports as any) as AsyncifyExportedFunctions;
+            if (this.isSleeping) {
+                // We are called as part of a resume/rewind. Stop sleeping.
+                exports.asyncify_stop_rewind();
+                this.isSleeping = false;
+                const pendingCalls = this.pendingHostFunctionCalls;
+                this.pendingHostFunctionCalls = [];
+                pendingCalls.forEach(call => {
+                    callHostFunction(call[0], call[1]);
+                });
+                return;
+            }
+
+            if (this.asyncifyBufferPointer == null) {
+                const runtimeExports = (this.instance
+                    .exports as any) as SwiftRuntimeExportedFunctions;
+                this.asyncifyBufferPointer = runtimeExports.swjs_allocate_asyncify_buffer(4096);
+            }
+            exports.asyncify_start_unwind(this.asyncifyBufferPointer!);
+            this.isSleeping = true;
+            const resume = () => {
+                exports.asyncify_start_rewind(this.asyncifyBufferPointer!);
+                this.resumeCallback();
+            };
+            promise
+                .then(result => {
+                    if (kind_ptr && payload1_ptr && payload2_ptr) {
+                        writeValue(result, kind_ptr, payload1_ptr, payload2_ptr, false);
+                    }
+                    resume();
+                })
+                .catch(error => {
+                    if (kind_ptr && payload1_ptr && payload2_ptr) {
+                        writeValue(error, kind_ptr, payload1_ptr, payload2_ptr, true);
+                    }
+                    queueMicrotask(resume);
+                });
+        };
+
         return {
             swjs_set_prop: (
                 ref: ref,
@@ -520,6 +636,18 @@ export class SwiftRuntime {
             swjs_release: (ref: ref) => {
                 this.heap.release(ref);
             },
+            swjs_sleep: (ms: number) => {
+                syncAwait(delay(ms));
+            },
+            swjs_sync_await: (
+                promiseRef: ref,
+                kind_ptr: pointer,
+                payload1_ptr: pointer,
+                payload2_ptr: pointer
+            ) => {
+                const promise: Promise<any> = this.heap.referenceHeap(promiseRef);
+                syncAwait(promise, kind_ptr, payload1_ptr, payload2_ptr);
+            },
         };
     }
 }
diff --git a/Sources/JavaScriptKit/PauseExecution.swift b/Sources/JavaScriptKit/PauseExecution.swift
new file mode 100644
index 000000000..c443e7e1c
--- /dev/null
+++ b/Sources/JavaScriptKit/PauseExecution.swift
@@ -0,0 +1,34 @@
+import _CJavaScriptKit
+
+/// Unwind Wasm module execution stack and rewind it after specified milliseconds,
+/// allowing JavaScript events to continue to be processed.
+/// **Important**: Wasm module must be [asyncified](https://emscripten.org/docs/porting/asyncify.html),
+/// otherwise JavaScriptKit's runtime will throw an exception.
+public func pauseExecution(milliseconds: Int32) {
+    _sleep(milliseconds)
+}
+
+
+extension JSPromise {
+    /// Unwind Wasm module execution stack and rewind it after promise resolves,
+    /// allowing JavaScript events to continue to be processed in the meantime.
+    /// - Parameters:
+    ///     - timeout: If provided, method will return a failure if promise cannot resolve
+    ///      before timeout is reached.
+    ///
+    /// **Important**: Wasm module must be [asyncified](https://emscripten.org/docs/porting/asyncify.html),
+    /// otherwise JavaScriptKit's runtime will throw an exception.
+    public func syncAwait() -> Result<JSValue, JSValue> {
+        var kindAndFlags = JavaScriptValueKindAndFlags()
+        var payload1 = JavaScriptPayload1()
+        var payload2 = JavaScriptPayload2()
+        
+        _syncAwait(jsObject.id, &kindAndFlags, &payload1, &payload2)
+        let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2).jsValue()
+        if kindAndFlags.isException {
+            return .failure(result)
+        } else {
+            return .success(result)
+        }
+    }
+}
diff --git a/Sources/JavaScriptKit/XcodeSupport.swift b/Sources/JavaScriptKit/XcodeSupport.swift
index 0777e911a..729ff3bf6 100644
--- a/Sources/JavaScriptKit/XcodeSupport.swift
+++ b/Sources/JavaScriptKit/XcodeSupport.swift
@@ -89,5 +89,19 @@ import _CJavaScriptKit
         _: Int32,
         _: UnsafeMutablePointer<JavaScriptObjectRef>!
     ) { fatalError() }
+    func _sleep(_: Int32) { fatalError() }
+    func _syncAwait(
+        _: JavaScriptObjectRef,
+        _: UnsafeMutablePointer<JavaScriptValueKindAndFlags>!,
+        _: UnsafeMutablePointer<JavaScriptPayload1>!,
+        _: UnsafeMutablePointer<JavaScriptPayload2>!
+    ) { fatalError() }
+    func _syncAwaitWithTimout(
+        _: JavaScriptObjectRef,
+        _: Int32,
+        _: UnsafeMutablePointer<JavaScriptValueKindAndFlags>!,
+        _: UnsafeMutablePointer<JavaScriptPayload1>!,
+        _: UnsafeMutablePointer<JavaScriptPayload2>!
+    ) { fatalError() }
 
 #endif
diff --git a/Sources/_CJavaScriptKit/_CJavaScriptKit.c b/Sources/_CJavaScriptKit/_CJavaScriptKit.c
index dd0f40959..93ab1d7e1 100644
--- a/Sources/_CJavaScriptKit/_CJavaScriptKit.c
+++ b/Sources/_CJavaScriptKit/_CJavaScriptKit.c
@@ -32,4 +32,19 @@ int _library_version() {
     return 701;
 }
 
+/// The structure pointing to the Asyncify stack buffer
+typedef struct __attribute__((packed)) {
+    void *start;
+    void *end;
+} _asyncify_data_pointer;
+
+__attribute__((export_name("swjs_allocate_asyncify_buffer")))
+void *_allocate_asyncify_buffer(const int size) {
+    void *buffer = malloc(size);
+    _asyncify_data_pointer *pointer = malloc(sizeof(_asyncify_data_pointer));
+    pointer->start = buffer;
+    pointer->end = (void *)((int)buffer + size);
+    return pointer;
+}
+
 #endif
diff --git a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h
index 6d383b3ea..12c51dbf9 100644
--- a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h
+++ b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h
@@ -258,6 +258,31 @@ extern void _create_typed_array(const JavaScriptObjectRef constructor,
                                 const void *elements_ptr, const int length,
                                 JavaScriptObjectRef *result_obj);
 
+/// Unwind Wasm module execution stack and rewind it after specified milliseconds,
+/// allowing JavaScript events to continue to be processed.
+/// **Important**: Wasm module must be [asyncified](https://emscripten.org/docs/porting/asyncify.html),
+/// otherwise JavaScriptKit's runtime will throw an exception.
+///
+/// @param ms Length of time in milliseconds to pause execution for.
+__attribute__((__import_module__("javascript_kit"),
+               __import_name__("swjs_sleep")))
+extern void _sleep(const int ms);
+
+/// Unwind Wasm module execution stack and rewind it after promise is fulfilled.
+/// **Important**: Wasm module must be [asyncified](https://emscripten.org/docs/porting/asyncify.html),
+/// otherwise JavaScriptKit's runtime will throw an exception.
+///
+/// @param promise target JavaScript promise.
+/// @param result_kind A result pointer of JavaScript value kind of returned result or thrown exception.
+/// @param result_payload1 A result pointer of first payload of JavaScript value of returned result or thrown exception.
+/// @param result_payload2 A result pointer of second payload of JavaScript value of returned result or thrown exception.
+__attribute__((__import_module__("javascript_kit"),
+               __import_name__("swjs_sync_await")))
+extern void _syncAwait(const JavaScriptObjectRef promise,
+                       JavaScriptValueKindAndFlags *result_kind,
+                       JavaScriptPayload1 *result_payload1,
+                       JavaScriptPayload2 *result_payload2);
+
 #endif
 
 #endif /* _CJavaScriptKit_h */