Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/js/src/builtin/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  DisposableStackObjectBase.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "builtin/DisposableStackObjectBase.h"

#include "builtin/Array.h"
#include "vm/ArrayObject.h"
#include "vm/Interpreter.h"

#include "vm/DisposableRecord-inl.h"
#include "vm/JSObject-inl.h"

using namespace js;

/**
 * Explicit Resource Management Proposal
 *
 * 27.4.3.1 AsyncDisposableStack.prototype.adopt ( value, onDisposeAsync )
 * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-asyncdisposablestack.prototype.adopt
 * Step 5.a
 * 27.3.3.1 DisposableStack.prototype.adopt ( value, onDispose )
 * https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-disposablestack.prototype.adopt
 * Step 5.a
 */

bool js::AdoptClosure(JSContext* cx, unsigned argc, JS::Value* vp) {
  JS::CallArgs args = CallArgsFromVp(argc, vp);

  JS::Rooted<JSFunction*> callee(cx, &args.callee().as<JSFunction>());
  JS::Rooted<JS::Value> value(
      cx, callee->getExtendedSlot(AdoptClosureSlot_ValueSlot));
  JS::Rooted<JS::Value> onDispose(
      cx, callee->getExtendedSlot(AdoptClosureSlot_OnDisposeSlot));

  // Step 5.a. Return ? Call(onDispose, undefined, « value »).
  return Call(cx, onDispose, JS::UndefinedHandleValue, value, args.rval());
}

bool js::ThrowIfOnDisposeNotCallable(JSContext* cx,
                                     JS::Handle<JS::Value> onDispose) {
  if (IsCallable(onDispose)) {
    return true;
  }

  JS::UniqueChars bytes =
      DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, onDispose, nullptr);
  if (!bytes) {
    return false;
  }

  JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_NOT_FUNCTION,
                           bytes.get());

  return false;
}

// Explicit Resource Management Proposal
// CreateDisposableResource ( V, hint [ , method ] )
// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource
// Steps 1, 3.
bool js::CreateDisposableResource(JSContext* cx, JS::Handle<JS::Value> objVal,
                                  UsingHint hint,
                                  JS::MutableHandle<JS::Value> result) {
  // Step 1. If method is not present, then
  // (implicit)
  JS::Rooted<JS::Value> method(cx);
  JS::Rooted<JS::Value> object(cx);
  // Step 1.a. If V is either null or undefined, then
  if (objVal.isNullOrUndefined()) {
    // Step 1.a.i. Set V to undefined.
    // Step 1.a.ii. Set method to undefined.
    object.setUndefined();
    method.setUndefined();
  } else {
    // Step 1.b. Else,
    // Step 1.b.i. If V is not an Object, throw a TypeError exception.
    if (!objVal.isObject()) {
      return ThrowCheckIsObject(cx, CheckIsObjectKind::Disposable);
    }

    // Step 1.b.ii. Set method to ? GetDisposeMethod(V, hint).
    // Step 1.b.iii. If method is undefined, throw a TypeError exception.
    object.set(objVal);
    if (!GetDisposeMethod(cx, object, hint, &method)) {
      return false;
    }
  }

  // Step 3. Return the
  //         DisposableResource Record { [[ResourceValue]]: V, [[Hint]]: hint,
  //         [[DisposeMethod]]: method }.
  DisposableRecordObject* disposableRecord =
      DisposableRecordObject::create(cx, object, method, hint);
  if (!disposableRecord) {
    return false;
  }
  result.set(ObjectValue(*disposableRecord));

  return true;
}

// Explicit Resource Management Proposal
// CreateDisposableResource ( V, hint [ , method ] )
// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource
// Steps 2, 3.
bool js::CreateDisposableResource(JSContext* cx, JS::Handle<JS::Value> obj,
                                  UsingHint hint,
                                  JS::Handle<JS::Value> methodVal,
                                  JS::MutableHandle<JS::Value> result) {
  JS::Rooted<JS::Value> method(cx);
  JS::Rooted<JS::Value> object(cx);

  // Step 2. Else,
  // Step 2.a. If IsCallable(method) is false, throw a TypeError exception.
  if (!IsCallable(methodVal)) {
    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_DISPOSE_NOT_CALLABLE);
    return false;
  }
  object.set(obj);
  method.set(methodVal);

  // Step 3. Return the
  //         DisposableResource Record { [[ResourceValue]]: V, [[Hint]]: hint,
  //         [[DisposeMethod]]: method }.
  DisposableRecordObject* disposableRecord =
      DisposableRecordObject::create(cx, object, method, hint);
  if (!disposableRecord) {
    return false;
  }
  result.set(ObjectValue(*disposableRecord));

  return true;
}

// Explicit Resource Management Proposal
// 7.5.4 AddDisposableResource ( disposeCapability, V, hint [ , method ] )
// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-adddisposableresource
// Steps 1, 3.
bool js::AddDisposableResource(JSContext* cx,
                               JS::Handle<ArrayObject*> disposeCapability,
                               JS::Handle<JS::Value> val, UsingHint hint) {
  JS::Rooted<JS::Value> resource(cx);

  // Step 1. If method is not present, then
  // (implicit)
  // Step 1.a. If V is either null or undefined and hint is sync-dispose,
  // return unused.
  if (val.isNullOrUndefined() && hint == UsingHint::Sync) {
    return true;
  }

  // Step 1.c. Let resource be ? CreateDisposableResource(V, hint).
  if (!CreateDisposableResource(cx, val, hint, &resource)) {
    return false;
  }

  // Step 3. Append resource to disposeCapability.[[DisposableResourceStack]].
  return NewbornArrayPush(cx, disposeCapability, resource);
}

// Explicit Resource Management Proposal
// 7.5.4 AddDisposableResource ( disposeCapability, V, hint [ , method ] )
// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-adddisposableresource
bool js::AddDisposableResource(JSContext* cx,
                               JS::Handle<ArrayObject*> disposeCapability,
                               JS::Handle<JS::Value> val, UsingHint hint,
                               JS::Handle<JS::Value> methodVal) {
  JS::Rooted<JS::Value> resource(cx);
  // Step 2. Else,
  // Step 2.a. Assert: V is undefined.
  MOZ_ASSERT(val.isUndefined());

  // Step 2.b. Let resource be ? CreateDisposableResource(undefined, hint,
  // method).
  if (!CreateDisposableResource(cx, val, hint, methodVal, &resource)) {
    return false;
  }
  // Step 3. Append resource to disposeCapability.[[DisposableResourceStack]].
  return NewbornArrayPush(cx, disposeCapability, resource);
}

// Explicit Resource Management Proposal
// GetDisposeMethod ( V, hint )
// https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-getdisposemethod
bool js::GetDisposeMethod(JSContext* cx, JS::Handle<JS::Value> objVal,
                          UsingHint hint,
                          JS::MutableHandle<JS::Value> disposeMethod) {
  switch (hint) {
    case UsingHint::Async: {
      // Step 1. If hint is async-dispose, then
      // Step 1.a. Let method be ? GetMethod(V, @@asyncDispose).
      // GetMethod throws TypeError if method is not callable
      // this is handled below at the end of the function.
      JS::Rooted<JS::PropertyKey> idAsync(
          cx, PropertyKey::Symbol(cx->wellKnownSymbols().asyncDispose));
      JS::Rooted<JSObject*> obj(cx, &objVal.toObject());

      if (!GetProperty(cx, obj, obj, idAsync, disposeMethod)) {
        return false;
      }

      // Step 1.b. If method is undefined, then
      // GetMethod returns undefined if the function is null but
      // since we do not do the conversion here we check for
      // null or undefined here.
      if (disposeMethod.isNullOrUndefined()) {
        // Step 1.b.i. Set method to ? GetMethod(V, @@dispose).
        JS::Rooted<JS::PropertyKey> idSync(
            cx, PropertyKey::Symbol(cx->wellKnownSymbols().dispose));
        JS::Rooted<JS::Value> syncDisposeMethod(cx);
        if (!GetProperty(cx, obj, obj, idSync, &syncDisposeMethod)) {
          return false;
        }

        if (!syncDisposeMethod.isNullOrUndefined()) {
          // Step 1.b.ii. If method is not undefined, then
          if (!IsCallable(syncDisposeMethod)) {
            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                                      JSMSG_DISPOSE_NOT_CALLABLE);
            return false;
          }

          // Step 1.b.ii.1. Let closure be a new Abstract Closure with no
          // parameters that captures method and performs the following steps
          // when called:
          // Steps 1.b.ii.1.a-f: See SyncDisposalClosure
          // Step 1.b.ii.3. Return CreateBuiltinFunction(closure, 0, "", « »).
          JS::Handle<PropertyName*> funName = cx->names().empty_;
          JSFunction* asyncWrapper = NewNativeFunction(
              cx, SyncDisposalClosure, 0, funName,
              gc::AllocKind::FUNCTION_EXTENDED, GenericObject);
          if (!asyncWrapper) {
            return false;
          }
          asyncWrapper->initExtendedSlot(
              uint8_t(SyncDisposalClosureSlots::Method), syncDisposeMethod);
          disposeMethod.set(JS::ObjectValue(*asyncWrapper));
        }
      }

      break;
    }

    case UsingHint::Sync: {
      // Step 2. Else,
      // Step 2.a. Let method be ? GetMethod(V, @@dispose).
      JS::Rooted<JS::PropertyKey> id(
          cx, PropertyKey::Symbol(cx->wellKnownSymbols().dispose));
      JS::Rooted<JSObject*> obj(cx, &objVal.toObject());

      if (!GetProperty(cx, obj, obj, id, disposeMethod)) {
        return false;
      }

      break;
    }
    default:
      MOZ_CRASH("Invalid UsingHint");
  }

  // CreateDisposableResource ( V, hint [ , method ] )
  // https://arai-a.github.io/ecma262-compare/?pr=3000&id=sec-createdisposableresource
  //
  // Step 1.b.iii. If method is undefined, throw a TypeError exception.
  if (disposeMethod.isNullOrUndefined() || !IsCallable(disposeMethod)) {
    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_DISPOSE_NOT_CALLABLE);
    return false;
  }

  return true;
}

/* static */ ArrayObject*
DisposableStackObjectBase::GetOrCreateDisposeCapability(
    JSContext* cx, JS::Handle<DisposableStackObjectBase*> obj) {
  ArrayObject* disposablesList = nullptr;

  if (obj->isDisposableResourceStackEmpty()) {
    disposablesList = NewDenseEmptyArray(cx);
    if (!disposablesList) {
      return nullptr;
    }
    obj->setReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT,
                         ObjectValue(*disposablesList));
  } else {
    disposablesList = obj->nonEmptyDisposableResourceStack();
  }

  return disposablesList;
}

bool DisposableStackObjectBase::isDisposableResourceStackEmpty() const {
  return getReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT).isUndefined();
}

void DisposableStackObjectBase::clearDisposableResourceStack() {
  setReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT, JS::UndefinedValue());
}

ArrayObject* DisposableStackObjectBase::nonEmptyDisposableResourceStack()
    const {
  MOZ_ASSERT(!isDisposableResourceStackEmpty());
  return &getReservedSlot(DISPOSABLE_RESOURCE_STACK_SLOT)
              .toObject()
              .as<ArrayObject>();
}

DisposableStackObjectBase::DisposableState DisposableStackObjectBase::state()
    const {
  return DisposableState(uint8_t(getReservedSlot(STATE_SLOT).toInt32()));
}

void DisposableStackObjectBase::setState(DisposableState state) {
  setReservedSlot(STATE_SLOT, JS::Int32Value(int32_t(state)));
}

Messung V0.5
C=90 H=97 G=93

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.