/*
 * Copyright 2016 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef wasm_pi_h
#define wasm_pi_h

#include "js/TypeDecls.h"
#include "vm/NativeObject.h"
#include "vm/PromiseObject.h"
#include "wasm/WasmAnyRef.h"
#include "wasm/WasmTypeDef.h"

// [SMDOC] JS Promise Integration
//
// The API provides relatively efficient and relatively ergonomic interop
// between JavaScript promises and WebAssembly but works under the constraint
// that the only changes are to the JS API and not to the core wasm.
//
// Here is a small example that uses JS Promise Integration API:
//
//     const suspending = new WebAssembly.Suspending(async () => 42)
//     const ins = wasmTextEval(`(module
//         (import "" "suspending" (func $imp (result i32)))
//         (func (export "entry") (result i32) (call $imp))
//     )`, {"": { suspending, }})
//     const promising = WebAssembly.promising(ins.exports.entry)
//     assertEq(await promising(), 42)
//
// The `new WebAssembly.Suspending(fn)` logic is implemented in a Wasm module
// generated by `SuspendingFunctionModuleFactory` utility (see WasmPI.cpp).
// The `WebAssembly.promising(wasmfn)` logic is implemented in a Wasm module
// generated by `PromisingFunctionModuleFactory` utility.
//
// See [SMDOC] Wasm Stack Switching in WasmStacks.cpp for the underlying
// continuation stack machinery that this API is built on.

namespace js {

class WasmStructObject;

namespace wasm {

class Context;

#ifdef ENABLE_WASM_JSPI

JSFunction* WasmSuspendingFunctionCreate(JSContext* cx, HandleObject func,
                                         uint32_t funcTypeIndex,
                                         const SharedTypeContext& typeContext);

JSFunction* WasmPromisingFunctionCreate(JSContext* cx, HandleObject func);

void* CreatePromise(Instance* instance);
void* GetPromiseResults(Instance* instance, void* promiseRef,
                        uint32_t typeIndex);
int32_t AddPromiseReactions(Instance* instance, void* promiseRef, void* contRef,
                            void* reactionRef, void* promisingPromiseRef);
void* PromiseResolve(Instance* instance, void* valueRef);
int32_t ResolvePromiseWithResults(Instance* instance, void* resultsRef,
                                  void* promiseRef);

#endif  // ENABLE_WASM_JSPI

}  // namespace wasm
}  // namespace js

#endif  // wasm_pi_h
