#include "src/builtins/builtins-utils-inl.h"
#include "src/builtins/builtins.h"
#include "src/common/globals.h"
#include "src/handles/maybe-handles.h"
#include "src/objects/casting.h"
#include "src/objects/contexts.h"
#include "src/objects/heap-object.h"
#include "src/objects/js-disposable-stack-inl.h"
#include "src/objects/js-disposable-stack.h"
#include "src/objects/js-function.h"
namespace v8 {
namespace internal {
BUILTIN(DisposableStackConstructor) {
const char* const kMethodName = "DisposableStack";
HandleScope scope(isolate);
isolate->CountUsage(v8::Isolate::kExplicitResourceManagement);
if (IsUndefined(*args.new_target(), isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
isolate->factory()->NewStringFromAsciiChecked(
kMethodName)));
}
DirectHandle<Map> map;
DirectHandle<JSFunction> target = args.target();
DirectHandle<JSReceiver> new_target = Cast<JSReceiver>(args.new_target());
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, map, JSFunction::GetDerivedMap(isolate, target, new_target));
DirectHandle<JSSyncDisposableStack> disposable_stack =
isolate->factory()->NewJSSyncDisposableStack(map);
JSDisposableStackBase::InitializeJSDisposableStackBase(isolate,
disposable_stack);
return *disposable_stack;
}
BUILTIN(DisposableStackPrototypeUse) {
const char* const kMethodName = "DisposableStack.prototype.use";
HandleScope scope(isolate);
CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
DirectHandle<JSAny> value = args.at<JSAny>(1);
if (disposable_stack->state() == DisposableStackState::kDisposed) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewReferenceError(
MessageTemplate::kDisposableStackIsDisposed,
isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
}
if (IsNullOrUndefined(*value)) {
return *value;
}
DirectHandle<Object> method;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, method,
JSDisposableStackBase::CheckValueAndGetDisposeMethod(
isolate, value, DisposeMethodHint::kSyncDispose));
JSDisposableStackBase::Add(isolate, disposable_stack, value, method,
DisposeMethodCallType::kValueIsReceiver,
DisposeMethodHint::kSyncDispose);
return *value;
}
BUILTIN(DisposableStackPrototypeDispose) {
const char* const kMethodName = "DisposableStack.prototype.dispose";
HandleScope scope(isolate);
CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
if (disposable_stack->state() == DisposableStackState::kDisposed) {
return ReadOnlyRoots(isolate).undefined_value();
}
disposable_stack->set_state(DisposableStackState::kDisposed);
DirectHandle<Object> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
JSDisposableStackBase::DisposeResources(
isolate, disposable_stack, DisposableStackResourcesType::kAllSync));
return ReadOnlyRoots(isolate).undefined_value();
}
BUILTIN(DisposableStackPrototypeGetDisposed) {
const char* const kMethodName = "get DisposableStack.prototype.disposed";
HandleScope scope(isolate);
CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
if (disposable_stack->state() == DisposableStackState::kDisposed) {
return ReadOnlyRoots(isolate).true_value();
}
return ReadOnlyRoots(isolate).false_value();
}
BUILTIN(DisposableStackPrototypeAdopt) {
const char* const kMethodName = "DisposableStack.prototype.adopt";
HandleScope scope(isolate);
DirectHandle<Object> value = args.at(1);
DirectHandle<Object> on_dispose = args.at(2);
CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
if (disposable_stack->state() == DisposableStackState::kDisposed) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewReferenceError(
MessageTemplate::kDisposableStackIsDisposed,
isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
}
if (!IsCallable(*on_dispose)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kNotCallable, on_dispose));
}
JSDisposableStackBase::Add(isolate, disposable_stack, value, on_dispose,
DisposeMethodCallType::kValueIsArgument,
DisposeMethodHint::kSyncDispose);
return *value;
}
BUILTIN(DisposableStackPrototypeDefer) {
const char* const kMethodName = "DisposableStack.prototype.defer";
HandleScope scope(isolate);
DirectHandle<Object> on_dispose = args.at(1);
CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
if (disposable_stack->state() == DisposableStackState::kDisposed) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewReferenceError(
MessageTemplate::kDisposableStackIsDisposed,
isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
}
if (!IsCallable(*on_dispose)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kNotCallable, on_dispose));
}
JSDisposableStackBase::Add(isolate, disposable_stack,
isolate->factory()->undefined_value(), on_dispose,
DisposeMethodCallType::kValueIsReceiver,
DisposeMethodHint::kSyncDispose);
return ReadOnlyRoots(isolate).undefined_value();
}
BUILTIN(DisposableStackPrototypeMove) {
const char* const kMethodName = "DisposableStack.prototype.move";
HandleScope scope(isolate);
CHECK_RECEIVER(JSSyncDisposableStack, disposable_stack, kMethodName);
if (disposable_stack->state() == DisposableStackState::kDisposed) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewReferenceError(
MessageTemplate::kDisposableStackIsDisposed,
isolate->factory()->NewStringFromAsciiChecked(kMethodName)));
}
Tagged<JSFunction> constructor_function =
Cast<JSFunction>(isolate->native_context()->GetNoCell(
Context::JS_DISPOSABLE_STACK_FUNCTION_INDEX));
DirectHandle<Map> map(constructor_function->initial_map(), isolate);
DirectHandle<JSSyncDisposableStack> new_disposable_stack =
isolate->factory()->NewJSSyncDisposableStack(map);
new_disposable_stack->set_stack(disposable_stack->stack());
new_disposable_stack->set_length(disposable_stack->length());
new_disposable_stack->set_state(DisposableStackState::kPending);
new_disposable_stack->set_error(*(isolate->factory()->uninitialized_value()));
new_disposable_stack->set_error_message(
*(isolate->factory()->uninitialized_value()));
disposable_stack->set_stack(ReadOnlyRoots(isolate).empty_fixed_array());
disposable_stack->set_length(0);
disposable_stack->set_error(*(isolate->factory()->uninitialized_value()));
disposable_stack->set_error_message(
*(isolate->factory()->uninitialized_value()));
disposable_stack->set_state(DisposableStackState::kDisposed);
return *new_disposable_stack;
}
}
}