#ifndef V8_OBJECTS_JS_DISPOSABLE_STACK_INL_H_
#define V8_OBJECTS_JS_DISPOSABLE_STACK_INL_H_
#include "src/objects/js-disposable-stack.h"
#include "src/execution/isolate.h"
#include "src/handles/handles.h"
#include "src/handles/maybe-handles.h"
#include "src/heap/factory.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/heap-object.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
#include "torque-generated/src/objects/js-disposable-stack-tq-inl.inc"
TQ_OBJECT_CONSTRUCTORS_IMPL(JSDisposableStackBase)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSSyncDisposableStack)
TQ_OBJECT_CONSTRUCTORS_IMPL(JSAsyncDisposableStack)
BIT_FIELD_ACCESSORS(JSDisposableStackBase, status, state,
JSDisposableStackBase::StateBit)
BIT_FIELD_ACCESSORS(JSDisposableStackBase, status, needs_await,
JSDisposableStackBase::NeedsAwaitBit)
BIT_FIELD_ACCESSORS(JSDisposableStackBase, status, has_awaited,
JSDisposableStackBase::HasAwaitedBit)
BIT_FIELD_ACCESSORS(JSDisposableStackBase, status, suppressed_error_created,
JSDisposableStackBase::SuppressedErrorCreatedBit)
BIT_FIELD_ACCESSORS(JSDisposableStackBase, status, length,
JSDisposableStackBase::LengthBits)
inline void JSDisposableStackBase::Add(
Isolate* isolate, DirectHandle<JSDisposableStackBase> disposable_stack,
DirectHandle<Object> value, DirectHandle<Object> method,
DisposeMethodCallType type, DisposeMethodHint hint) {
DCHECK(!IsUndefined(disposable_stack->stack()));
int length = disposable_stack->length();
int stack_type =
DisposeCallTypeBit::encode(type) | DisposeHintBit::encode(hint);
DirectHandle<Smi> stack_type_handle(Smi::FromInt(stack_type), isolate);
Handle<FixedArray> array(disposable_stack->stack(), isolate);
array = FixedArray::SetAndGrow(isolate, array, length++, value);
array = FixedArray::SetAndGrow(isolate, array, length++, method);
array = FixedArray::SetAndGrow(isolate, array, length++, stack_type_handle);
disposable_stack->set_length(length);
disposable_stack->set_stack(*array);
}
inline MaybeDirectHandle<Object>
JSDisposableStackBase::CheckValueAndGetDisposeMethod(Isolate* isolate,
DirectHandle<JSAny> value,
DisposeMethodHint hint) {
DirectHandle<Object> method;
if (hint == DisposeMethodHint::kSyncDispose) {
DCHECK(!IsNullOrUndefined(*value));
if (!IsJSReceiver(*value)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kExpectAnObjectWithUsing));
}
ASSIGN_RETURN_ON_EXCEPTION(
isolate, method,
Object::GetProperty(isolate, value,
isolate->factory()->dispose_symbol()));
if (!IsCallable(*method)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kNotCallable,
isolate->factory()->dispose_symbol()));
}
} else if (hint == DisposeMethodHint::kAsyncDispose) {
if (IsNullOrUndefined(*value)) {
return isolate->factory()->undefined_value();
}
if (!IsJSReceiver(*value)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kExpectAnObjectWithUsing));
}
ASSIGN_RETURN_ON_EXCEPTION(
isolate, method,
Object::GetProperty(isolate, value,
isolate->factory()->async_dispose_symbol()));
if (IsNullOrUndefined(*method)) {
ASSIGN_RETURN_ON_EXCEPTION(
isolate, method,
Object::GetProperty(isolate, value,
isolate->factory()->dispose_symbol()));
if (!IsCallable(*method)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kNotCallable,
isolate->factory()->dispose_symbol()));
}
if (!IsUndefined(*method)) {
DirectHandle<Context> async_dispose_from_sync_dispose_context =
isolate->factory()->NewBuiltinContext(
isolate->native_context(),
static_cast<int>(
AsyncDisposeFromSyncDisposeContextSlots::kLength));
async_dispose_from_sync_dispose_context->SetNoCell(
static_cast<int>(AsyncDisposeFromSyncDisposeContextSlots::kMethod),
*method);
method =
Factory::JSFunctionBuilder{
isolate,
isolate->factory()
->async_dispose_from_sync_dispose_shared_fun(),
async_dispose_from_sync_dispose_context}
.Build();
}
}
if (!IsCallable(*method)) {
THROW_NEW_ERROR(isolate,
NewTypeError(MessageTemplate::kNotCallable,
isolate->factory()->async_dispose_symbol()));
}
}
return method;
}
inline void JSDisposableStackBase::HandleErrorInDisposal(
Isolate* isolate, DirectHandle<JSDisposableStackBase> disposable_stack,
DirectHandle<Object> current_error,
DirectHandle<Object> current_error_message) {
DCHECK(isolate->is_catchable_by_javascript(*current_error));
DirectHandle<Object> maybe_error(disposable_stack->error(), isolate);
if (!IsUninitializedHole(*maybe_error)) {
maybe_error = isolate->factory()->NewSuppressedErrorAtDisposal(
isolate, current_error, maybe_error);
disposable_stack->set_suppressed_error_created(true);
} else {
maybe_error = current_error;
}
disposable_stack->set_error(*maybe_error);
disposable_stack->set_error_message(*current_error_message);
}
}
}
#include "src/objects/object-macros-undef.h"
#endif