/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/objects/js-disposable-stack-inl.h
222 строки
9 KB
Michaël Zasso
deps: update V8 to 14.1.146.11
04 окт 2025, 19:47
Не верифицирован
04 окт 2025, 19:47
7772a2d
Код
Авторство
О чём код?
// Copyright 2024 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_OBJECTS_JS_DISPOSABLE_STACK_INL_H_ #define V8_OBJECTS_JS_DISPOSABLE_STACK_INL_H_ #include "src/objects/js-disposable-stack.h" // Include the non-inl header before the rest of the headers. #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" // Has to be the last include (doesn't have include guards): #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); } // part of // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource inline MaybeDirectHandle<Object> JSDisposableStackBase::CheckValueAndGetDisposeMethod(Isolate* isolate, DirectHandle<JSAny> value, DisposeMethodHint hint) { DirectHandle<Object> method; if (hint == DisposeMethodHint::kSyncDispose) { // 1. If method is not present, then // a. If V is either null or undefined, then // i. Set V to undefined. // ii. Set method to undefined. // We has already returned from the caller if V is null or undefined, when // hint is `kSyncDispose`. DCHECK(!IsNullOrUndefined(*value)); // b. Else, // i. If V is not an Object, throw a TypeError exception. if (!IsJSReceiver(*value)) { THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kExpectAnObjectWithUsing)); } // ii. Set method to ? GetDisposeMethod(V, hint). ASSIGN_RETURN_ON_EXCEPTION( isolate, method, Object::GetProperty(isolate, value, isolate->factory()->dispose_symbol())); // (GetMethod)3. If IsCallable(func) is false, throw a TypeError // exception. if (!IsCallable(*method)) { THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kNotCallable, isolate->factory()->dispose_symbol())); } // iii. If method is undefined, throw a TypeError exception. // It is already checked in step ii. } else if (hint == DisposeMethodHint::kAsyncDispose) { // 1. If method is not present, then // a. If V is either null or undefined, then // i. Set V to undefined. // ii. Set method to undefined. if (IsNullOrUndefined(*value)) { return isolate->factory()->undefined_value(); } // b. Else, // i. If V is not an Object, throw a TypeError exception. if (!IsJSReceiver(*value)) { THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kExpectAnObjectWithUsing)); } // https://tc39.es/proposal-explicit-resource-management/#sec-getdisposemethod // 1. If hint is async-dispose, then // a. Let method be ? GetMethod(V, @@asyncDispose). ASSIGN_RETURN_ON_EXCEPTION( isolate, method, Object::GetProperty(isolate, value, isolate->factory()->async_dispose_symbol())); // b. If method is undefined, then if (IsNullOrUndefined(*method)) { // i. Set method to ? GetMethod(V, @@dispose). ASSIGN_RETURN_ON_EXCEPTION( isolate, method, Object::GetProperty(isolate, value, isolate->factory()->dispose_symbol())); // (GetMethod)3. If IsCallable(func) is false, throw a TypeError // exception. if (!IsCallable(*method)) { THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kNotCallable, isolate->factory()->dispose_symbol())); } // ii. If method is not undefined, then if (!IsUndefined(*method)) { // 1. Let closure be a new Abstract Closure with no parameters that // captures method and performs the following steps when called: // a. Let O be the this value. // b. Let promiseCapability be ! NewPromiseCapability(%Promise%). // c. Let result be Completion(Call(method, O)). // d. IfAbruptRejectPromise(result, promiseCapability). // e. Perform ? Call(promiseCapability.[[Resolve]], undefined, « // undefined »). // f. Return promiseCapability.[[Promise]]. // 2. NOTE: This function is not observable to user code. It is // used to ensure that a Promise returned from a synchronous // @@dispose method will not be awaited and that any exception // thrown will not be thrown synchronously. // 3. Return CreateBuiltinFunction(closure, 0, "", « »). // (TODO:rezvan): Add `kAsyncFromSyncDispose` to the `DisposeMethodHint` // enum and remove the following allocation of adapter closure. 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(); } } // (GetMethod)3. If IsCallable(func) is false, throw a TypeError // exception. 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); // i. If completion is a throw completion, then if (!IsUninitializedHole(*maybe_error)) { // 1. Set result to result.[[Value]]. // 2. Let suppressed be completion.[[Value]]. // 3. Let error be a newly created SuppressedError object. // 4. Perform CreateNonEnumerableDataPropertyOrThrow(error, "error", // result). // 5. Perform CreateNonEnumerableDataPropertyOrThrow(error, // "suppressed", suppressed). // 6. Set completion to ThrowCompletion(error). maybe_error = isolate->factory()->NewSuppressedErrorAtDisposal( isolate, current_error, maybe_error); disposable_stack->set_suppressed_error_created(true); } else { // ii. Else, // 1. Set completion to result. maybe_error = current_error; } disposable_stack->set_error(*maybe_error); disposable_stack->set_error_message(*current_error_message); } } // namespace internal } // namespace v8 #include "src/objects/object-macros-undef.h" #endif // V8_OBJECTS_JS_DISPOSABLE_STACK_INL_H_