/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/builtins/iterator.tq
416 строк
16 KB
Michaël Zasso
deps: update V8 to 14.6.202.33
24 апр 2026, 19:01
Не верифицирован
24 апр 2026, 19:01
f1e0b83
Код
Авторство
О чём код?
// Copyright 2018 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. #include 'src/builtins/builtins-iterator-gen.h' namespace iterator { // Returned from IteratorBuiltinsAssembler::GetIterator(). @export struct IteratorRecord { // iteratorRecord.[[Iterator]] object: JSReceiver; // iteratorRecord.[[NextMethod]] next: JSAny; } extern macro IteratorBuiltinsAssembler::FastIterableToList( implicit context: Context)(JSAny): JSArray labels Slow; extern transitioning macro IteratorBuiltinsAssembler::GetIteratorMethod( implicit context: Context)(JSAny): JSAny; extern transitioning macro IteratorBuiltinsAssembler::GetIterator( implicit context: Context)(JSAny): IteratorRecord; extern transitioning macro IteratorBuiltinsAssembler::GetIterator( implicit context: Context)(JSAny, JSAny): IteratorRecord; extern transitioning macro IteratorBuiltinsAssembler::IteratorStep( implicit context: Context)(IteratorRecord): JSReceiver labels Done; extern transitioning macro IteratorBuiltinsAssembler::IteratorStep( implicit context: Context)(IteratorRecord, Map): JSReceiver labels Done; extern transitioning macro IteratorBuiltinsAssembler::IteratorComplete( implicit context: Context)(JSReceiver): void labels Done; extern transitioning macro IteratorBuiltinsAssembler::IteratorComplete( implicit context: Context)(JSReceiver, Map): void labels Done; extern transitioning macro IteratorBuiltinsAssembler::IteratorValue( implicit context: Context)(JSReceiver): JSAny; extern transitioning macro IteratorBuiltinsAssembler::IteratorValue( implicit context: Context)(JSReceiver, Map): JSAny; extern transitioning macro IteratorBuiltinsAssembler::IterableToList( implicit context: Context)(JSAny, JSAny): JSArray; extern transitioning macro IteratorBuiltinsAssembler::StringListFromIterable( implicit context: Context)(JSAny): JSArray; extern transitioning builtin IterableToListWithSymbolLookup( implicit context: Context)(JSAny): JSArray; extern transitioning builtin IterableToFixedArrayWithSymbolLookupSlow( implicit context: Context)(JSAny): FixedArray; extern transitioning runtime ObjectHasOwnProperty(Context, JSAny, JSAny): Boolean; transitioning builtin GetIteratorWithFeedback( context: Context, receiver: JSAny, loadSlot: TaggedIndex, callSlot: TaggedIndex, maybeFeedbackVector: Undefined|FeedbackVector): JSAny { // TODO(v8:9891): Remove this dcheck once all callers are ported to Torque. // This dcheck ensures correctness of maybeFeedbackVector's type which can // be easily broken for calls from CSA. dcheck( IsUndefined(maybeFeedbackVector) || Is<FeedbackVector>(maybeFeedbackVector)); let iteratorMethod: JSAny; typeswitch (maybeFeedbackVector) { case (Undefined): { iteratorMethod = GetProperty(receiver, IteratorSymbolConstant()); } case (feedback: FeedbackVector): { iteratorMethod = LoadIC( context, receiver, IteratorSymbolConstant(), loadSlot, feedback); } } // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it. const callSlotSmi: Smi = TaggedIndexToSmi(callSlot); return CallIteratorWithFeedback( context, receiver, iteratorMethod, callSlotSmi, maybeFeedbackVector); } extern macro LoadContextFromBaseline(): Context; extern macro LoadFeedbackVectorFromBaseline(): FeedbackVector; transitioning builtin GetIteratorBaseline( receiver: JSAny, loadSlot: TaggedIndex, callSlot: TaggedIndex): JSAny { const context: Context = LoadContextFromBaseline(); const feedback: FeedbackVector = LoadFeedbackVectorFromBaseline(); const iteratorMethod: JSAny = LoadIC(context, receiver, IteratorSymbolConstant(), loadSlot, feedback); // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it. const callSlotSmi: Smi = TaggedIndexToSmi(callSlot); return CallIteratorWithFeedback( context, receiver, iteratorMethod, callSlotSmi, feedback); } extern transitioning macro CreateAsyncFromSyncIterator(Context, JSAny): JSAny; transitioning builtin CreateAsyncFromSyncIteratorBaseline(syncIterator: JSAny): JSAny { const context: Context = LoadContextFromBaseline(); return CreateAsyncFromSyncIterator(context, syncIterator); } struct ForOfNextResult { value: Object; done: Object; } extern transitioning macro ForOfNextHelper( Context, Object, Object, Undefined|FeedbackVector, uintptr): ForOfNextResult; transitioning builtin ForOfNext( context: Context, iterator: JSAny, next: JSFunction, feedbackVector: Undefined|FeedbackVector, callSlot: Smi): ForOfNextResult { return ForOfNextHelper( context, iterator, next, feedbackVector, Unsigned(SmiUntag(callSlot))); } transitioning builtin ForOfNextBaseline( context: Context, iterator: JSAny, next: JSFunction, resultSlot: RawPtr, callSlot: Smi): Undefined { const feedbackVector = LoadFeedbackVectorFromBaseline(); const result: ForOfNextResult = ForOfNextHelper( context, iterator, next, feedbackVector, Unsigned(SmiUntag(callSlot))); // The result slot address points to the first interpreter register slot. const firstResultSlot = resultSlot; // The second interpreter register slot is one word before, since stacks grow // toward zero. const secondResultSlot = resultSlot + torque_internal::TimesSizeOf<intptr>(-1); StoreFullTaggedNoWriteBarrier(firstResultSlot, result.value); StoreFullTaggedNoWriteBarrier(secondResultSlot, result.done); return Undefined; } @export transitioning macro GetIteratorRecordAfterCreateAsyncFromSyncIterator( context: Context, asyncIterator: IteratorRecord): IteratorRecord { const iterator = CreateAsyncFromSyncIterator(context, asyncIterator.object); const nextMethod = GetProperty(iterator, kNextString); return IteratorRecord{ object: UnsafeCast<JSReceiver>(iterator), next: nextMethod }; } macro GetLazyReceiver(receiver: JSAny): JSAny { return receiver; } transitioning builtin CallIteratorWithFeedback( context: Context, receiver: JSAny, iteratorMethod: JSAny, callSlot: Smi, feedback: Undefined|FeedbackVector): JSAny { // TODO(v8:10047): Use TaggedIndex here once TurboFan supports it. const callSlotUnTagged: uintptr = Unsigned(SmiUntag(callSlot)); ic::CollectCallFeedback( iteratorMethod, %MakeLazy<JSAny, JSAny>('GetLazyReceiver', receiver), context, feedback, callSlotUnTagged); const iteratorCallable: Callable = Cast<Callable>(iteratorMethod) otherwise ThrowIteratorError(receiver); const iterator = Call(context, iteratorCallable, receiver); ThrowIfNotJSReceiver(iterator, MessageTemplate::kSymbolIteratorInvalid, ''); return iterator; } // https://tc39.es/ecma262/#sec-iteratorclose // IteratorCloseOnException should be used to close iterators due to exceptions // being thrown. @export transitioning macro IteratorCloseOnException( implicit context: Context)(iteratorObject: JSReceiver): void { try { // 3. Let innerResult be GetMethod(iterator, "return"). const method = GetProperty(iteratorObject, kReturnString); // 4. If innerResult.[[Type]] is normal, then // a. Let return be innerResult.[[Value]]. // b. If return is undefined, return Completion(completion). if (method == Undefined || method == Null) return; // c. Set innerResult to Call(return, iterator). // If an exception occurs, the original exception remains bound Call(context, method, iteratorObject); } catch (_e, _message) { // Swallow the exception. } // (5. If completion.[[Type]] is throw) return Completion(completion). } @export transitioning macro IteratorClose( implicit context: Context)(iterator: IteratorRecord): void { // 3. Let innerResult be GetMethod(iterator, "return"). const method = GetProperty(iterator.object, kReturnString); // 4. If innerResult.[[Type]] is normal, then // a. Let return be innerResult.[[Value]]. // b. If return is undefined, return Completion(completion). if (method == Undefined || method == Null) return; // c. Set innerResult to Call(return, iterator). const result = Call(context, method, iterator.object); // 5. If completion.[[Type]] is throw, return Completion(completion). // It is handled in IteratorCloseOnException. // 7. If innerResult.[[Value]] is not an Object, throw a TypeError // exception. Cast<JSReceiver>(result) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, 'return'); } // https://tc39.es/ecma262/#sec-iterator transitioning javascript builtin IteratorConstructor( js-implicit context: NativeContext, receiver: JSAny, newTarget: JSAny, target: JSFunction)(): JSObject { const methodName: constexpr string = 'Iterator'; // 1. If NewTarget is undefined or the active function object, throw a // TypeError exception. if (newTarget == Undefined) { ThrowTypeError(MessageTemplate::kConstructorNotFunction, methodName); } if (newTarget == target) { ThrowTypeError(MessageTemplate::kConstructAbstractClass, methodName); } // 2. Return ? OrdinaryCreateFromConstructor(NewTarget, // "%Iterator.prototype%"). const map = GetDerivedMap(target, UnsafeCast<JSReceiver>(newTarget)); return AllocateFastOrSlowJSObjectFromMap(map); } // https://tc39.es/ecma262/#sec-SetterThatIgnoresPrototypeProperties transitioning macro SetterThatIgnoresPrototypeProperties( implicit context: Context)(receiver: JSAny, home: JSObject, key: JSAny, value: JSAny, methodName: constexpr string): JSAny { // 1. If this is not an Object, then // a. Throw a TypeError exception. const o = Cast<JSReceiver>(receiver) otherwise ThrowTypeError(MessageTemplate::kCalledOnNonObject, methodName); // 2. If this is home, then // a. NOTE: Throwing here emulates assignment to a non-writable data // property on the home object in strict mode code. b. Throw a TypeError // exception. if (o == home) { ThrowTypeError( MessageTemplate::kStrictReadOnlyProperty, key, objectStringConstant(), home); } // 3. Let desc be ? this.[[GetOwnProperty]](p). const hasOwn = ObjectHasOwnProperty(context, o, key); // 4. If desc is undefined, then if (hasOwn == False) { // a. Perform ? CreateDataPropertyOrThrow(this, p, v). CreateDataProperty(o, key, value); } else { // 5. Else, // a. Perform ? Set(this, p, v, true). SetProperty(o, key, value); } // 6. Return unused. return Undefined; } // https://tc39.es/ecma262/#sec-get-iteratorprototype-@@tostringtag transitioning javascript builtin IteratorPrototypeGetToStringTag( js-implicit context: NativeContext)(): JSAny { // 1. Return "Iterator". return IteratorStringConstant(); } // https://tc39.es/ecma262/#sec-set-iteratorprototype-@@tostringtag transitioning javascript builtin IteratorPrototypeSetToStringTag( js-implicit context: NativeContext, receiver: JSAny)(value: JSAny): JSAny { // 1. Perform ? SetterThatIgnoresPrototypeProperties(this value, // %Iterator.prototype%, %Symbol.toStringTag%, v). const methodName: constexpr string = 'set Iterator.prototype[Symbol.toStringTag]'; SetterThatIgnoresPrototypeProperties( receiver, GetIteratorPrototype(), ToStringTagSymbolConstant(), value, methodName); // 2. Return undefined. return Undefined; } // https://tc39.es/ecma262/#sec-get-iteratorprototype-constructor transitioning javascript builtin IteratorPrototypeGetConstructor( js-implicit context: NativeContext)(): JSAny { // 1. Return %Iterator%. return GetIteratorFunction(); } // https://tc39.es/ecma262/#sec-set-iteratorprototype-constructor transitioning javascript builtin IteratorPrototypeSetConstructor( js-implicit context: NativeContext, receiver: JSAny)(value: JSAny): JSAny { // 1. Perform ? SetterThatIgnoresPrototypeProperties(this value, // %Iterator.prototype%, "constructor", v). const methodName: constexpr string = 'set Iterator.prototype.constructor'; SetterThatIgnoresPrototypeProperties( receiver, GetIteratorPrototype(), ConstructorStringConstant(), value, methodName); // 2. Return undefined. return Undefined; } // https://tc39.es/proposal-explicit-resource-management/#sec-%iteratorprototype%-@@dispose transitioning javascript builtin IteratorPrototypeDispose( js-implicit context: NativeContext, receiver: JSAny)(): JSAny { // 1. Let O be the this value. // 2. Let return be ? GetMethod(O, "return"). try { const returnMethod = GetMethod(receiver, kReturnString) otherwise IfUndefined; // 3. If return is not undefined, then // a. Perform ? Call(return, O, « »). Call(context, returnMethod, receiver); } label IfUndefined { // Do nothing here } // 4. Return NormalCompletion(undefined). return Undefined; } extern macro AllocateRootFunctionWithContext( constexpr intptr, FunctionContext, NativeContext): JSFunction; extern macro AsyncIteratorPrototypeAsyncDisposeResolveClosureSharedFunConstant(): SharedFunctionInfo; const kAsyncIteratorPrototypeAsyncDisposeResolveClosureSharedFun: constexpr intptr generates 'RootIndex::kAsyncIteratorPrototypeAsyncDisposeResolveClosureSharedFun' ; type AsyncIteratorPrototypeAsyncDisposeResolveContext extends FunctionContext; const kAsyncIteratorPrototypeAsyncDisposeResolveContextLength: constexpr intptr = ContextSlot::MIN_CONTEXT_SLOTS; javascript builtin AsyncIteratorPrototypeAsyncDisposeResolveClosure( js-implicit context: NativeContext, receiver: JSAny)(): JSAny { return Undefined; } // https://tc39.es/proposal-explicit-resource-management/#sec-%asynciteratorprototype%-@@asyncdispose transitioning javascript builtin AsyncIteratorPrototypeAsyncDispose( js-implicit context: Context, receiver: JSAny)(): JSAny { // 1. Let O be the this value. // 2. Let promiseCapability be ! NewPromiseCapability(%Promise%). const capability = promise::NewJSPromise(); try { try { // 3. Let return be GetMethod(O, "return"). // 4. IfAbruptRejectPromise(return, promiseCapability). const returnMethod = GetMethod(receiver, kReturnString) otherwise IfUndefined; // 6. Else, // a. Let result be Call(return, O, « undefined »). // b. IfAbruptRejectPromise(result, promiseCapability). const result = Call(context, returnMethod, receiver, Undefined); // c. Let resultWrapper be Completion(PromiseResolve(%Promise%, result)). // d. IfAbruptRejectPromise(resultWrapper, promiseCapability). const promiseFun = *NativeContextSlot( ContextSlot::PROMISE_FUNCTION_INDEX); const resultWrapper = promise::PromiseResolve(promiseFun, result); // e. Let unwrap be a new Abstract Closure that performs the following // steps when called: i. Return undefined. // f. Let onFulfilled be CreateBuiltinFunction(unwrap, 1, "", « »). const resolveContext = %RawDownCast<AsyncIteratorPrototypeAsyncDisposeResolveContext>( AllocateSyntheticFunctionContext( %RawDownCast<NativeContext>(context), kAsyncIteratorPrototypeAsyncDisposeResolveContextLength)); const onFulfilled = AllocateRootFunctionWithContext( kAsyncIteratorPrototypeAsyncDisposeResolveClosureSharedFun, resolveContext, %RawDownCast<NativeContext>(context)); // g. Perform PerformPromiseThen(resultWrapper, onFulfilled, undefined, // promiseCapability). promise::PerformPromiseThenImpl( UnsafeCast<JSPromise>(resultWrapper), onFulfilled, UndefinedConstant(), capability); } label IfUndefined { // 5. If return is undefined, then // a. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined // »). promise::ResolvePromise(capability, Undefined); } // 7. Return promiseCapability.[[Promise]]. return capability; } catch (e, _message) { promise::RejectPromise(capability, e, False); return capability; } } } // namespace iterator