11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_API_API_INL_H_
61cb0ef41Sopenharmony_ci#define V8_API_API_INL_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "include/v8-fast-api-calls.h"
91cb0ef41Sopenharmony_ci#include "src/api/api.h"
101cb0ef41Sopenharmony_ci#include "src/execution/interrupts-scope.h"
111cb0ef41Sopenharmony_ci#include "src/execution/microtask-queue.h"
121cb0ef41Sopenharmony_ci#include "src/execution/protectors.h"
131cb0ef41Sopenharmony_ci#include "src/handles/handles-inl.h"
141cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h"
151cb0ef41Sopenharmony_ci#include "src/objects/foreign-inl.h"
161cb0ef41Sopenharmony_ci#include "src/objects/js-weak-refs.h"
171cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cinamespace v8 {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_citemplate <typename T>
221cb0ef41Sopenharmony_ciinline T ToCData(v8::internal::Object obj) {
231cb0ef41Sopenharmony_ci  STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
241cb0ef41Sopenharmony_ci  if (obj == v8::internal::Smi::zero()) return nullptr;
251cb0ef41Sopenharmony_ci  return reinterpret_cast<T>(
261cb0ef41Sopenharmony_ci      v8::internal::Foreign::cast(obj).foreign_address());
271cb0ef41Sopenharmony_ci}
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_citemplate <>
301cb0ef41Sopenharmony_ciinline v8::internal::Address ToCData(v8::internal::Object obj) {
311cb0ef41Sopenharmony_ci  if (obj == v8::internal::Smi::zero()) return v8::internal::kNullAddress;
321cb0ef41Sopenharmony_ci  return v8::internal::Foreign::cast(obj).foreign_address();
331cb0ef41Sopenharmony_ci}
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_citemplate <typename T>
361cb0ef41Sopenharmony_ciinline v8::internal::Handle<v8::internal::Object> FromCData(
371cb0ef41Sopenharmony_ci    v8::internal::Isolate* isolate, T obj) {
381cb0ef41Sopenharmony_ci  STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
391cb0ef41Sopenharmony_ci  if (obj == nullptr) return handle(v8::internal::Smi::zero(), isolate);
401cb0ef41Sopenharmony_ci  return isolate->factory()->NewForeign(
411cb0ef41Sopenharmony_ci      reinterpret_cast<v8::internal::Address>(obj));
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_citemplate <>
451cb0ef41Sopenharmony_ciinline v8::internal::Handle<v8::internal::Object> FromCData(
461cb0ef41Sopenharmony_ci    v8::internal::Isolate* isolate, v8::internal::Address obj) {
471cb0ef41Sopenharmony_ci  if (obj == v8::internal::kNullAddress) {
481cb0ef41Sopenharmony_ci    return handle(v8::internal::Smi::zero(), isolate);
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci  return isolate->factory()->NewForeign(obj);
511cb0ef41Sopenharmony_ci}
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_citemplate <class From, class To>
541cb0ef41Sopenharmony_ciinline Local<To> Utils::Convert(v8::internal::Handle<From> obj) {
551cb0ef41Sopenharmony_ci  DCHECK(obj.is_null() || (obj->IsSmi() || !obj->IsTheHole()));
561cb0ef41Sopenharmony_ci  return Local<To>(reinterpret_cast<To*>(obj.location()));
571cb0ef41Sopenharmony_ci}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci// Implementations of ToLocal
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ci#define MAKE_TO_LOCAL(Name, From, To)                                       \
621cb0ef41Sopenharmony_ci  Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
631cb0ef41Sopenharmony_ci    return Convert<v8::internal::From, v8::To>(obj);                        \
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci#define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype)        \
671cb0ef41Sopenharmony_ci  Local<v8::Type##Array> Utils::ToLocal##Type##Array(                 \
681cb0ef41Sopenharmony_ci      v8::internal::Handle<v8::internal::JSTypedArray> obj) {         \
691cb0ef41Sopenharmony_ci    DCHECK(obj->type() == v8::internal::kExternal##Type##Array);      \
701cb0ef41Sopenharmony_ci    return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, AccessorPair, debug::AccessorPair)
741cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, Context, Context)
751cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, Object, Value)
761cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, Module, Module)
771cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, Name, Name)
781cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, String, String)
791cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
801cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
811cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSReceiver, Object)
821cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSObject, Object)
831cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSFunction, Function)
841cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSArray, Array)
851cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSMap, Map)
861cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSSet, Set)
871cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSProxy, Proxy)
881cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
891cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
901cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
911cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
921cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer)
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ciTYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY)
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
971cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
981cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(SignatureToLocal, FunctionTemplateInfo, Signature)
991cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature)
1001cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(MessageToLocal, Object, Message)
1011cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise)
1021cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(StackTraceToLocal, FixedArray, StackTrace)
1031cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(StackFrameToLocal, StackFrameInfo, StackFrame)
1041cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(NumberToLocal, Object, Number)
1051cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
1061cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
1071cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, BigInt, BigInt)
1081cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
1091cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function)
1101cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocalPrimitive, Object, Primitive)
1111cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(FixedArrayToLocal, FixedArray, FixedArray)
1121cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(PrimitiveArrayToLocal, FixedArray, PrimitiveArray)
1131cb0ef41Sopenharmony_ciMAKE_TO_LOCAL(ToLocal, ScriptOrModule, ScriptOrModule)
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci#undef MAKE_TO_LOCAL_TYPED_ARRAY
1161cb0ef41Sopenharmony_ci#undef MAKE_TO_LOCAL
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci// Implementations of OpenHandle
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci#define MAKE_OPEN_HANDLE(From, To)                                    \
1211cb0ef41Sopenharmony_ci  v8::internal::Handle<v8::internal::To> Utils::OpenHandle(           \
1221cb0ef41Sopenharmony_ci      const v8::From* that, bool allow_empty_handle) {                \
1231cb0ef41Sopenharmony_ci    DCHECK(allow_empty_handle || that != nullptr);                    \
1241cb0ef41Sopenharmony_ci    DCHECK(that == nullptr ||                                         \
1251cb0ef41Sopenharmony_ci           v8::internal::Object(                                      \
1261cb0ef41Sopenharmony_ci               *reinterpret_cast<const v8::internal::Address*>(that)) \
1271cb0ef41Sopenharmony_ci               .Is##To());                                            \
1281cb0ef41Sopenharmony_ci    return v8::internal::Handle<v8::internal::To>(                    \
1291cb0ef41Sopenharmony_ci        reinterpret_cast<v8::internal::Address*>(                     \
1301cb0ef41Sopenharmony_ci            const_cast<v8::From*>(that)));                            \
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ciOPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci#undef MAKE_OPEN_HANDLE
1361cb0ef41Sopenharmony_ci#undef OPEN_HANDLE_LIST
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_citemplate <bool do_callback>
1391cb0ef41Sopenharmony_ciclass V8_NODISCARD CallDepthScope {
1401cb0ef41Sopenharmony_ci public:
1411cb0ef41Sopenharmony_ci  CallDepthScope(i::Isolate* isolate, Local<Context> context)
1421cb0ef41Sopenharmony_ci      : isolate_(isolate),
1431cb0ef41Sopenharmony_ci        context_(context),
1441cb0ef41Sopenharmony_ci        did_enter_context_(false),
1451cb0ef41Sopenharmony_ci        escaped_(false),
1461cb0ef41Sopenharmony_ci        safe_for_termination_(isolate->next_v8_call_is_safe_for_termination()),
1471cb0ef41Sopenharmony_ci        interrupts_scope_(isolate_, i::StackGuard::TERMINATE_EXECUTION,
1481cb0ef41Sopenharmony_ci                          isolate_->only_terminate_in_safe_scope()
1491cb0ef41Sopenharmony_ci                              ? (safe_for_termination_
1501cb0ef41Sopenharmony_ci                                     ? i::InterruptsScope::kRunInterrupts
1511cb0ef41Sopenharmony_ci                                     : i::InterruptsScope::kPostponeInterrupts)
1521cb0ef41Sopenharmony_ci                              : i::InterruptsScope::kNoop) {
1531cb0ef41Sopenharmony_ci    isolate_->thread_local_top()->IncrementCallDepth(this);
1541cb0ef41Sopenharmony_ci    isolate_->set_next_v8_call_is_safe_for_termination(false);
1551cb0ef41Sopenharmony_ci    if (!context.IsEmpty()) {
1561cb0ef41Sopenharmony_ci      i::Handle<i::Context> env = Utils::OpenHandle(*context);
1571cb0ef41Sopenharmony_ci      i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
1581cb0ef41Sopenharmony_ci      if (isolate->context().is_null() ||
1591cb0ef41Sopenharmony_ci          isolate->context().native_context() != env->native_context()) {
1601cb0ef41Sopenharmony_ci        impl->SaveContext(isolate->context());
1611cb0ef41Sopenharmony_ci        isolate->set_context(*env);
1621cb0ef41Sopenharmony_ci        did_enter_context_ = true;
1631cb0ef41Sopenharmony_ci      }
1641cb0ef41Sopenharmony_ci    }
1651cb0ef41Sopenharmony_ci    if (do_callback) isolate_->FireBeforeCallEnteredCallback();
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci  ~CallDepthScope() {
1681cb0ef41Sopenharmony_ci    i::MicrotaskQueue* microtask_queue = isolate_->default_microtask_queue();
1691cb0ef41Sopenharmony_ci    if (!context_.IsEmpty()) {
1701cb0ef41Sopenharmony_ci      if (did_enter_context_) {
1711cb0ef41Sopenharmony_ci        i::HandleScopeImplementer* impl = isolate_->handle_scope_implementer();
1721cb0ef41Sopenharmony_ci        isolate_->set_context(impl->RestoreContext());
1731cb0ef41Sopenharmony_ci      }
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci      i::Handle<i::Context> env = Utils::OpenHandle(*context_);
1761cb0ef41Sopenharmony_ci      microtask_queue = env->native_context().microtask_queue();
1771cb0ef41Sopenharmony_ci    }
1781cb0ef41Sopenharmony_ci    if (!escaped_) isolate_->thread_local_top()->DecrementCallDepth(this);
1791cb0ef41Sopenharmony_ci    if (do_callback) isolate_->FireCallCompletedCallback(microtask_queue);
1801cb0ef41Sopenharmony_ci#ifdef DEBUG
1811cb0ef41Sopenharmony_ci    if (do_callback) {
1821cb0ef41Sopenharmony_ci      if (microtask_queue && microtask_queue->microtasks_policy() ==
1831cb0ef41Sopenharmony_ci                                 v8::MicrotasksPolicy::kScoped) {
1841cb0ef41Sopenharmony_ci        DCHECK(microtask_queue->GetMicrotasksScopeDepth() ||
1851cb0ef41Sopenharmony_ci               !microtask_queue->DebugMicrotasksScopeDepthIsZero());
1861cb0ef41Sopenharmony_ci      }
1871cb0ef41Sopenharmony_ci    }
1881cb0ef41Sopenharmony_ci#endif
1891cb0ef41Sopenharmony_ci    DCHECK(CheckKeptObjectsClearedAfterMicrotaskCheckpoint(microtask_queue));
1901cb0ef41Sopenharmony_ci    isolate_->set_next_v8_call_is_safe_for_termination(safe_for_termination_);
1911cb0ef41Sopenharmony_ci  }
1921cb0ef41Sopenharmony_ci
1931cb0ef41Sopenharmony_ci  CallDepthScope(const CallDepthScope&) = delete;
1941cb0ef41Sopenharmony_ci  CallDepthScope& operator=(const CallDepthScope&) = delete;
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ci  void Escape() {
1971cb0ef41Sopenharmony_ci    DCHECK(!escaped_);
1981cb0ef41Sopenharmony_ci    escaped_ = true;
1991cb0ef41Sopenharmony_ci    auto thread_local_top = isolate_->thread_local_top();
2001cb0ef41Sopenharmony_ci    thread_local_top->DecrementCallDepth(this);
2011cb0ef41Sopenharmony_ci    bool clear_exception = thread_local_top->CallDepthIsZero() &&
2021cb0ef41Sopenharmony_ci                           thread_local_top->try_catch_handler_ == nullptr;
2031cb0ef41Sopenharmony_ci    isolate_->OptionalRescheduleException(clear_exception);
2041cb0ef41Sopenharmony_ci  }
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci private:
2071cb0ef41Sopenharmony_ci  bool CheckKeptObjectsClearedAfterMicrotaskCheckpoint(
2081cb0ef41Sopenharmony_ci      i::MicrotaskQueue* microtask_queue) {
2091cb0ef41Sopenharmony_ci    bool did_perform_microtask_checkpoint =
2101cb0ef41Sopenharmony_ci        isolate_->thread_local_top()->CallDepthIsZero() && do_callback &&
2111cb0ef41Sopenharmony_ci        microtask_queue &&
2121cb0ef41Sopenharmony_ci        microtask_queue->microtasks_policy() == MicrotasksPolicy::kAuto;
2131cb0ef41Sopenharmony_ci    return !did_perform_microtask_checkpoint ||
2141cb0ef41Sopenharmony_ci           isolate_->heap()->weak_refs_keep_during_job().IsUndefined(isolate_);
2151cb0ef41Sopenharmony_ci  }
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  i::Isolate* const isolate_;
2181cb0ef41Sopenharmony_ci  Local<Context> context_;
2191cb0ef41Sopenharmony_ci  bool did_enter_context_ : 1;
2201cb0ef41Sopenharmony_ci  bool escaped_ : 1;
2211cb0ef41Sopenharmony_ci  bool safe_for_termination_ : 1;
2221cb0ef41Sopenharmony_ci  i::InterruptsScope interrupts_scope_;
2231cb0ef41Sopenharmony_ci  i::Address previous_stack_height_;
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  friend class i::ThreadLocalTop;
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  DISALLOW_NEW_AND_DELETE()
2281cb0ef41Sopenharmony_ci};
2291cb0ef41Sopenharmony_ci
2301cb0ef41Sopenharmony_ciclass V8_NODISCARD InternalEscapableScope : public EscapableHandleScope {
2311cb0ef41Sopenharmony_ci public:
2321cb0ef41Sopenharmony_ci  explicit inline InternalEscapableScope(i::Isolate* isolate)
2331cb0ef41Sopenharmony_ci      : EscapableHandleScope(reinterpret_cast<v8::Isolate*>(isolate)) {}
2341cb0ef41Sopenharmony_ci};
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ciinline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
2371cb0ef41Sopenharmony_ci  if (isolate->has_scheduled_exception()) {
2381cb0ef41Sopenharmony_ci    return isolate->scheduled_exception() ==
2391cb0ef41Sopenharmony_ci           i::ReadOnlyRoots(isolate).termination_exception();
2401cb0ef41Sopenharmony_ci  }
2411cb0ef41Sopenharmony_ci  return false;
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_citemplate <typename T>
2451cb0ef41Sopenharmony_civoid CopySmiElementsToTypedBuffer(T* dst, uint32_t length,
2461cb0ef41Sopenharmony_ci                                  i::FixedArray elements) {
2471cb0ef41Sopenharmony_ci  for (uint32_t i = 0; i < length; ++i) {
2481cb0ef41Sopenharmony_ci    double value = elements.get(static_cast<int>(i)).Number();
2491cb0ef41Sopenharmony_ci    // TODO(mslekova): Avoid converting back-and-forth when possible, e.g
2501cb0ef41Sopenharmony_ci    // avoid int->double->int conversions to boost performance.
2511cb0ef41Sopenharmony_ci    dst[i] = i::ConvertDouble<T>(value);
2521cb0ef41Sopenharmony_ci  }
2531cb0ef41Sopenharmony_ci}
2541cb0ef41Sopenharmony_ci
2551cb0ef41Sopenharmony_citemplate <typename T>
2561cb0ef41Sopenharmony_civoid CopyDoubleElementsToTypedBuffer(T* dst, uint32_t length,
2571cb0ef41Sopenharmony_ci                                     i::FixedDoubleArray elements) {
2581cb0ef41Sopenharmony_ci  for (uint32_t i = 0; i < length; ++i) {
2591cb0ef41Sopenharmony_ci    double value = elements.get_scalar(static_cast<int>(i));
2601cb0ef41Sopenharmony_ci    // TODO(mslekova): There are certain cases, e.g. double->double, in which
2611cb0ef41Sopenharmony_ci    // we could do a memcpy directly.
2621cb0ef41Sopenharmony_ci    dst[i] = i::ConvertDouble<T>(value);
2631cb0ef41Sopenharmony_ci  }
2641cb0ef41Sopenharmony_ci}
2651cb0ef41Sopenharmony_ci
2661cb0ef41Sopenharmony_citemplate <CTypeInfo::Identifier type_info_id, typename T>
2671cb0ef41Sopenharmony_cibool CopyAndConvertArrayToCppBuffer(Local<Array> src, T* dst,
2681cb0ef41Sopenharmony_ci                                    uint32_t max_length) {
2691cb0ef41Sopenharmony_ci  static_assert(
2701cb0ef41Sopenharmony_ci      std::is_same<T, typename i::CTypeInfoTraits<
2711cb0ef41Sopenharmony_ci                          CTypeInfo(type_info_id).GetType()>::ctype>::value,
2721cb0ef41Sopenharmony_ci      "Type mismatch between the expected CTypeInfo::Type and the destination "
2731cb0ef41Sopenharmony_ci      "array");
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci  uint32_t length = src->Length();
2761cb0ef41Sopenharmony_ci  if (length > max_length) {
2771cb0ef41Sopenharmony_ci    return false;
2781cb0ef41Sopenharmony_ci  }
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci  i::DisallowGarbageCollection no_gc;
2811cb0ef41Sopenharmony_ci  i::JSArray obj = *reinterpret_cast<i::JSArray*>(*src);
2821cb0ef41Sopenharmony_ci  if (obj.IterationHasObservableEffects()) {
2831cb0ef41Sopenharmony_ci    // The array has a custom iterator.
2841cb0ef41Sopenharmony_ci    return false;
2851cb0ef41Sopenharmony_ci  }
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  i::FixedArrayBase elements = obj.elements();
2881cb0ef41Sopenharmony_ci  switch (obj.GetElementsKind()) {
2891cb0ef41Sopenharmony_ci    case i::PACKED_SMI_ELEMENTS:
2901cb0ef41Sopenharmony_ci      CopySmiElementsToTypedBuffer(dst, length, i::FixedArray::cast(elements));
2911cb0ef41Sopenharmony_ci      return true;
2921cb0ef41Sopenharmony_ci    case i::PACKED_DOUBLE_ELEMENTS:
2931cb0ef41Sopenharmony_ci      CopyDoubleElementsToTypedBuffer(dst, length,
2941cb0ef41Sopenharmony_ci                                      i::FixedDoubleArray::cast(elements));
2951cb0ef41Sopenharmony_ci      return true;
2961cb0ef41Sopenharmony_ci    default:
2971cb0ef41Sopenharmony_ci      return false;
2981cb0ef41Sopenharmony_ci  }
2991cb0ef41Sopenharmony_ci}
3001cb0ef41Sopenharmony_ci
3011cb0ef41Sopenharmony_ci// Deprecated; to be removed.
3021cb0ef41Sopenharmony_citemplate <const CTypeInfo* type_info, typename T>
3031cb0ef41Sopenharmony_ciinline bool V8_EXPORT TryCopyAndConvertArrayToCppBuffer(Local<Array> src,
3041cb0ef41Sopenharmony_ci                                                        T* dst,
3051cb0ef41Sopenharmony_ci                                                        uint32_t max_length) {
3061cb0ef41Sopenharmony_ci  return CopyAndConvertArrayToCppBuffer<type_info->GetId(), T>(src, dst,
3071cb0ef41Sopenharmony_ci                                                               max_length);
3081cb0ef41Sopenharmony_ci}
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_citemplate <CTypeInfo::Identifier type_info_id, typename T>
3111cb0ef41Sopenharmony_ciinline bool V8_EXPORT TryToCopyAndConvertArrayToCppBuffer(Local<Array> src,
3121cb0ef41Sopenharmony_ci                                                          T* dst,
3131cb0ef41Sopenharmony_ci                                                          uint32_t max_length) {
3141cb0ef41Sopenharmony_ci  return CopyAndConvertArrayToCppBuffer<type_info_id, T>(src, dst, max_length);
3151cb0ef41Sopenharmony_ci}
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_cinamespace internal {
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_civoid HandleScopeImplementer::EnterContext(Context context) {
3201cb0ef41Sopenharmony_ci  DCHECK_EQ(entered_contexts_.capacity(), is_microtask_context_.capacity());
3211cb0ef41Sopenharmony_ci  DCHECK_EQ(entered_contexts_.size(), is_microtask_context_.size());
3221cb0ef41Sopenharmony_ci  DCHECK(context.IsNativeContext());
3231cb0ef41Sopenharmony_ci  entered_contexts_.push_back(context);
3241cb0ef41Sopenharmony_ci  is_microtask_context_.push_back(0);
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_civoid HandleScopeImplementer::EnterMicrotaskContext(Context context) {
3281cb0ef41Sopenharmony_ci  DCHECK_EQ(entered_contexts_.capacity(), is_microtask_context_.capacity());
3291cb0ef41Sopenharmony_ci  DCHECK_EQ(entered_contexts_.size(), is_microtask_context_.size());
3301cb0ef41Sopenharmony_ci  DCHECK(context.IsNativeContext());
3311cb0ef41Sopenharmony_ci  entered_contexts_.push_back(context);
3321cb0ef41Sopenharmony_ci  is_microtask_context_.push_back(1);
3331cb0ef41Sopenharmony_ci}
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ciHandle<Context> HandleScopeImplementer::LastEnteredContext() {
3361cb0ef41Sopenharmony_ci  DCHECK_EQ(entered_contexts_.capacity(), is_microtask_context_.capacity());
3371cb0ef41Sopenharmony_ci  DCHECK_EQ(entered_contexts_.size(), is_microtask_context_.size());
3381cb0ef41Sopenharmony_ci
3391cb0ef41Sopenharmony_ci  for (size_t i = 0; i < entered_contexts_.size(); ++i) {
3401cb0ef41Sopenharmony_ci    size_t j = entered_contexts_.size() - i - 1;
3411cb0ef41Sopenharmony_ci    if (!is_microtask_context_.at(j)) {
3421cb0ef41Sopenharmony_ci      return Handle<Context>(entered_contexts_.at(j), isolate_);
3431cb0ef41Sopenharmony_ci    }
3441cb0ef41Sopenharmony_ci  }
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci  return Handle<Context>::null();
3471cb0ef41Sopenharmony_ci}
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ciHandle<Context> HandleScopeImplementer::LastEnteredOrMicrotaskContext() {
3501cb0ef41Sopenharmony_ci  if (entered_contexts_.empty()) return Handle<Context>::null();
3511cb0ef41Sopenharmony_ci  return Handle<Context>(entered_contexts_.back(), isolate_);
3521cb0ef41Sopenharmony_ci}
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ci}  // namespace internal
3551cb0ef41Sopenharmony_ci}  // namespace v8
3561cb0ef41Sopenharmony_ci
3571cb0ef41Sopenharmony_ci#endif  // V8_API_API_INL_H_
358