// Copyright 2021 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" #include "src/builtins/builtins-utils-gen.h" #include "src/builtins/growable-fixed-array-gen.h" #include "src/codegen/code-stub-assembler.h" #include "src/objects/js-temporal-objects-inl.h" #include "src/objects/objects-inl.h" #include "src/objects/objects.h" namespace v8 { namespace internal { class TemporalBuiltinsAssembler : public IteratorBuiltinsAssembler { public: explicit TemporalBuiltinsAssembler(compiler::CodeAssemblerState* state) : IteratorBuiltinsAssembler(state) {} // For the use inside Temporal GetPossibleInstantFor TNode TemporalInstantFixedArrayFromIterable( TNode context, TNode iterable); }; // #sec-iterabletolistoftype TNode TemporalBuiltinsAssembler::TemporalInstantFixedArrayFromIterable( TNode context, TNode iterable) { GrowableFixedArray list(state()); Label done(this); // 1. If iterable is undefined, then // a. Return a new empty List. GotoIf(IsUndefined(iterable), &done); // 2. Let iteratorRecord be ? GetIterator(items). IteratorRecord iterator_record = GetIterator(context, iterable); // 3. Let list be a new empty List. Label loop_start(this, {list.var_array(), list.var_length(), list.var_capacity()}); Goto(&loop_start); // 4. Let next be true. // 5. Repeat, while next is not false Label if_isnottemporalinstant(this, Label::kDeferred), if_exception(this, Label::kDeferred); BIND(&loop_start); { // a. Set next to ? IteratorStep(iteratorRecord). TNode next = IteratorStep(context, iterator_record, &done); // b. If next is not false, then // i. Let nextValue be ? IteratorValue(next). TNode next_value = IteratorValue(context, next); // ii. If Type(nextValue) is not Object or nextValue does not have an // [[InitializedTemporalInstant]] internal slot GotoIf(TaggedIsSmi(next_value), &if_isnottemporalinstant); TNode next_value_type = LoadInstanceType(CAST(next_value)); GotoIfNot(IsTemporalInstantInstanceType(next_value_type), &if_isnottemporalinstant); // iii. Append nextValue to the end of the List list. list.Push(next_value); Goto(&loop_start); // 5.b.ii BIND(&if_isnottemporalinstant); { // 1. Let error be ThrowCompletion(a newly created TypeError object). TVARIABLE(Object, var_exception); { compiler::ScopedExceptionHandler handler(this, &if_exception, &var_exception); CallRuntime(Runtime::kThrowTypeError, context, SmiConstant(MessageTemplate::kIterableYieldedNonString), next_value); } Unreachable(); // 2. Return ? IteratorClose(iteratorRecord, error). BIND(&if_exception); IteratorCloseOnException(context, iterator_record); CallRuntime(Runtime::kReThrow, context, var_exception.value()); Unreachable(); } } BIND(&done); return list.ToFixedArray(); } TF_BUILTIN(TemporalInstantFixedArrayFromIterable, TemporalBuiltinsAssembler) { auto context = Parameter(Descriptor::kContext); auto iterable = Parameter(Descriptor::kIterable); Return(TemporalInstantFixedArrayFromIterable(context, iterable)); } } // namespace internal } // namespace v8