Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  PlainYearMonth.cpp

  Sprache: C
 

/* 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/temporal/PlainYearMonth.h"

#include "mozilla/Assertions.h"

#include "jspubtd.h"
#include "NamespaceImports.h"

#include "builtin/intl/DateTimeFormat.h"
#include "builtin/temporal/Calendar.h"
#include "builtin/temporal/CalendarFields.h"
#include "builtin/temporal/Duration.h"
#include "builtin/temporal/Instant.h"
#include "builtin/temporal/PlainDate.h"
#include "builtin/temporal/PlainDateTime.h"
#include "builtin/temporal/PlainMonthDay.h"
#include "builtin/temporal/Temporal.h"
#include "builtin/temporal/TemporalParser.h"
#include "builtin/temporal/TemporalRoundingMode.h"
#include "builtin/temporal/TemporalTypes.h"
#include "builtin/temporal/TemporalUnit.h"
#include "builtin/temporal/TimeZone.h"
#include "builtin/temporal/ToString.h"
#include "gc/AllocKind.h"
#include "gc/Barrier.h"
#include "gc/GCEnum.h"
#include "js/CallArgs.h"
#include "js/CallNonGenericMethod.h"
#include "js/Class.h"
#include "js/ErrorReport.h"
#include "js/friend/ErrorMessages.h"
#include "js/PropertyDescriptor.h"
#include "js/PropertySpec.h"
#include "js/RootingAPI.h"
#include "js/TypeDecls.h"
#include "js/Value.h"
#include "vm/BytecodeUtil.h"
#include "vm/GlobalObject.h"
#include "vm/JSAtomState.h"
#include "vm/JSContext.h"
#include "vm/JSObject.h"
#include "vm/PlainObject.h"
#include "vm/StringType.h"

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

using namespace js;
using namespace js::temporal;

static inline bool IsPlainYearMonth(Handle<Value> v) {
  return v.isObject() && v.toObject().is<PlainYearMonthObject>();
}

/**
 * ISOYearMonthWithinLimits ( isoDate )
 */

bool js::temporal::ISOYearMonthWithinLimits(const ISODate& isoDate) {
  MOZ_ASSERT(IsValidISODate(isoDate));

  constexpr auto min = ISODate::min();
  constexpr auto max = ISODate::max();

  const auto& year = isoDate.year;

  // Fast-path when the input is definitely in range.
  if (min.year < year && year < max.year) {
    return true;
  }

  // Check |isoDate| is within the valid limits.
  if (year < 0) {
    return isoDate >= ISODate{min.year, min.month, 1};
  }
  return isoDate < ISODate{max.year, max.month + 11};
}

/**
 * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] )
 */

static PlainYearMonthObject* CreateTemporalYearMonth(
    JSContext* cx, const CallArgs& args, const ISODate& isoDate,
    Handle<CalendarValue> calendar) {
  // Step 1.
  if (!ISOYearMonthWithinLimits(isoDate)) {
    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID);
    return nullptr;
  }

  // Steps 2-3.
  Rooted<JSObject*> proto(cx);
  if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_PlainYearMonth,
                                          &proto)) {
    return nullptr;
  }

  auto* object = NewObjectWithClassProto<PlainYearMonthObject>(cx, proto);
  if (!object) {
    return nullptr;
  }

  // Step 4.
  auto packedDate = PackedDate::pack(isoDate);
  object->initFixedSlot(PlainYearMonthObject::PACKED_DATE_SLOT,
                        PrivateUint32Value(packedDate.value));

  // Step 5.
  object->initFixedSlot(PlainYearMonthObject::CALENDAR_SLOT,
                        calendar.toSlotValue());

  // Step 6.
  return object;
}

/**
 * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] )
 */

PlainYearMonthObject* js::temporal::CreateTemporalYearMonth(
    JSContext* cx, Handle<PlainYearMonth> yearMonth) {
  MOZ_ASSERT(IsValidISODate(yearMonth));

  // Step 1.
  MOZ_ASSERT(ISOYearMonthWithinLimits(yearMonth));

  // Steps 2-3.
  auto* object = NewBuiltinClassInstance<PlainYearMonthObject>(cx);
  if (!object) {
    return nullptr;
  }

  // Step 4.
  auto packedDate = PackedDate::pack(yearMonth);
  object->initFixedSlot(PlainYearMonthObject::PACKED_DATE_SLOT,
                        PrivateUint32Value(packedDate.value));

  // Step 5.
  object->initFixedSlot(PlainYearMonthObject::CALENDAR_SLOT,
                        yearMonth.calendar().toSlotValue());

  // Step 6.
  return object;
}

/**
 * CreateTemporalYearMonth ( isoDate, calendar [ , newTarget ] )
 */

bool js::temporal::CreateTemporalYearMonth(
    JSContext* cx, const ISODate& isoDate, Handle<CalendarValue> calendar,
    MutableHandle<PlainYearMonth> result) {
  MOZ_ASSERT(IsValidISODate(isoDate));

  // Step 1.
  if (!ISOYearMonthWithinLimits(isoDate)) {
    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_INVALID);
    return false;
  }

  // Steps 2-6.
  result.set(PlainYearMonth{isoDate, calendar});
  return true;
}

struct YearMonthOptions {
  TemporalOverflow overflow = TemporalOverflow::Constrain;
};

/**
 * ToTemporalYearMonth ( item [ , options ] )
 */

static bool ToTemporalYearMonthOptions(JSContext* cx, Handle<Value> options,
                                       YearMonthOptions* result) {
  if (options.isUndefined()) {
    *result = {};
    return true;
  }

  // NOTE: |options| are only passed from `Temporal.PlainYearMonth.from`.

  Rooted<JSObject*> resolvedOptions(
      cx, RequireObjectArg(cx, "options""from", options));
  if (!resolvedOptions) {
    return false;
  }

  auto overflow = TemporalOverflow::Constrain;
  if (!GetTemporalOverflowOption(cx, resolvedOptions, &overflow)) {
    return false;
  }

  *result = {overflow};
  return true;
}

/**
 * ToTemporalYearMonth ( item [ , options ] )
 */

static bool ToTemporalYearMonth(JSContext* cx, Handle<JSObject*> item,
                                Handle<Value> options,
                                MutableHandle<PlainYearMonth> result) {
  // Step 1. (Not applicable in our implementation.)

  // Step 2.a.
  if (auto* plainYearMonth = item->maybeUnwrapIf<PlainYearMonthObject>()) {
    auto date = plainYearMonth->date();
    Rooted<CalendarValue> calendar(cx, plainYearMonth->calendar());
    if (!calendar.wrap(cx)) {
      return false;
    }

    // Steps 2.a.i-ii.
    YearMonthOptions ignoredOptions;
    if (!ToTemporalYearMonthOptions(cx, options, &ignoredOptions)) {
      return false;
    }

    // Step 2.a.iii.
    result.set(PlainYearMonth{date, calendar});
    return true;
  }

  // Step 2.b.
  Rooted<CalendarValue> calendar(cx);
  if (!GetTemporalCalendarWithISODefault(cx, item, &calendar)) {
    return false;
  }

  // Step 2.c.
  Rooted<CalendarFields> fields(cx);
  if (!PrepareCalendarFields(cx, calendar, item,
                             {
                                 CalendarField::Year,
                                 CalendarField::Month,
                                 CalendarField::MonthCode,
                             },
                             &fields)) {
    return false;
  }

  // Steps 2.d-e.
  YearMonthOptions resolvedOptions;
  if (!ToTemporalYearMonthOptions(cx, options, &resolvedOptions)) {
    return false;
  }
  auto [overflow] = resolvedOptions;

  // Step 2.f.
  return CalendarYearMonthFromFields(cx, calendar, fields, overflow, result);
}

/**
 * ToTemporalYearMonth ( item [ , options ] )
 */

static bool ToTemporalYearMonth(JSContext* cx, Handle<Value> item,
                                Handle<Value> options,
                                MutableHandle<PlainYearMonth> result) {
  // Step 1. (Not applicable in our implementation.)

  // Step 2.
  if (item.isObject()) {
    Rooted<JSObject*> itemObj(cx, &item.toObject());
    return ToTemporalYearMonth(cx, itemObj, options, result);
  }

  // Step 3.
  if (!item.isString()) {
    ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, item,
                     nullptr, "not a string");
    return false;
  }
  Rooted<JSString*> string(cx, item.toString());

  // Step 4.
  ISODate date;
  Rooted<JSString*> calendarString(cx);
  if (!ParseTemporalYearMonthString(cx, string, &date, &calendarString)) {
    return false;
  }

  // Steps 5-7.
  Rooted<CalendarValue> calendar(cx, CalendarValue(CalendarId::ISO8601));
  if (calendarString) {
    if (!CanonicalizeCalendar(cx, calendarString, &calendar)) {
      return false;
    }
  }

  // Steps 8-9.
  YearMonthOptions ignoredOptions;
  if (!ToTemporalYearMonthOptions(cx, options, &ignoredOptions)) {
    return false;
  }

  // Step 10-11.
  Rooted<PlainYearMonth> yearMonth(cx);
  if (!CreateTemporalYearMonth(cx, date, calendar, &yearMonth)) {
    return false;
  }

  // Step 12.
  Rooted<CalendarFields> fields(cx);
  if (!ISODateToFields(cx, yearMonth, &fields)) {
    return false;
  }

  // Steps 13-14.
  return CalendarYearMonthFromFields(cx, calendar, fields,
                                     TemporalOverflow::Constrain, result);
}

/**
 * ToTemporalYearMonth ( item [ , options ] )
 */

static bool ToTemporalYearMonth(JSContext* cx, Handle<Value> item,
                                MutableHandle<PlainYearMonth> result) {
  return ToTemporalYearMonth(cx, item, UndefinedHandleValue, result);
}

/**
 * DifferenceTemporalPlainYearMonth ( operation, yearMonth, other, options )
 */

static bool DifferenceTemporalPlainYearMonth(JSContext* cx,
                                             TemporalDifference operation,
                                             const CallArgs& args) {
  Rooted<PlainYearMonth> yearMonth(
      cx, &args.thisv().toObject().as<PlainYearMonthObject>());

  // Step 1.
  Rooted<PlainYearMonth> other(cx);
  if (!ToTemporalYearMonth(cx, args.get(0), &other)) {
    return false;
  }

  // Step 2.
  auto calendar = yearMonth.calendar();

  // Step 3.
  if (!CalendarEquals(calendar, other.calendar())) {
    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_TEMPORAL_CALENDAR_INCOMPATIBLE,
                              CalendarIdentifier(calendar).data(),
                              CalendarIdentifier(other.calendar()).data());
    return false;
  }

  // Steps 4-5.
  DifferenceSettings settings;
  Rooted<PlainObject*> resolvedOptions(cx);
  if (args.hasDefined(1)) {
    // Step 4.
    Rooted<JSObject*> options(
        cx, RequireObjectArg(cx, "options", ToName(operation), args[1]));
    if (!options) {
      return false;
    }

    // Step 5.
    if (!GetDifferenceSettings(cx, operation, options, TemporalUnitGroup::Date,
                               TemporalUnit::Month, TemporalUnit::Month,
                               TemporalUnit::Year, &settings)) {
      return false;
    }
  } else {
    // Steps 4-5.
    settings = {
        TemporalUnit::Month,
        TemporalUnit::Year,
        TemporalRoundingMode::Trunc,
        Increment{1},
    };
  }

  // Step 6.
  if (yearMonth.date() == other.date()) {
    auto* obj = CreateTemporalDuration(cx, {});
    if (!obj) {
      return false;
    }

    args.rval().setObject(*obj);
    return true;
  }

  // Step 7.
  Rooted<CalendarFields> thisFields(cx);
  if (!ISODateToFields(cx, yearMonth, &thisFields)) {
    return false;
  }

  // Step 8.
  MOZ_ASSERT(!thisFields.has(CalendarField::Day));
  thisFields.setDay(1);

  // Step 9.
  Rooted<PlainDate> thisDate(cx);
  if (!CalendarDateFromFields(cx, calendar, thisFields,
                              TemporalOverflow::Constrain, &thisDate)) {
    return false;
  }

  // Step 10.
  Rooted<CalendarFields> otherFields(cx);
  if (!ISODateToFields(cx, other, &otherFields)) {
    return false;
  }

  // Step 11.
  MOZ_ASSERT(!otherFields.has(CalendarField::Day));
  otherFields.setDay(1);

  // Step 12.
  Rooted<PlainDate> otherDate(cx);
  if (!CalendarDateFromFields(cx, calendar, otherFields,
                              TemporalOverflow::Constrain, &otherDate)) {
    return false;
  }

  // Step 13.
  DateDuration until;
  if (!CalendarDateUntil(cx, calendar, thisDate, otherDate,
                         settings.largestUnit, &until)) {
    return false;
  }

  // Step 14. (Inlined AdjustDateDurationRecord)
  //
  // We only care about years and months here, all other fields are set to zero.
  auto dateDuration = DateDuration{until.years, until.months};

  // Step 15.
  auto duration = InternalDuration{dateDuration, {}};

  // Step 16.
  if (settings.smallestUnit != TemporalUnit::Month ||
      settings.roundingIncrement != Increment{1}) {
    // Step 16.a.
    auto isoDateTime = ISODateTime{thisDate, {}};

    // Step 16.b.
    auto originEpochNs = GetUTCEpochNanoseconds(isoDateTime);

    // Step 16.c.
    auto isoDateTimeOther = ISODateTime{otherDate, {}};

    // Step 16.d.
    auto destEpochNs = GetUTCEpochNanoseconds(isoDateTimeOther);

    // Step 16.e.
    Rooted<TimeZoneValue> timeZone(cx, TimeZoneValue{});
    if (!RoundRelativeDuration(
            cx, duration, originEpochNs, destEpochNs, isoDateTime, timeZone,
            calendar, settings.largestUnit, settings.roundingIncrement,
            settings.smallestUnit, settings.roundingMode, &duration)) {
      return false;
    }
  }
  MOZ_ASSERT(IsValidDuration(duration));
  MOZ_ASSERT(duration.date.weeks == 0);
  MOZ_ASSERT(duration.date.days == 0);
  MOZ_ASSERT(duration.time == TimeDuration{});

  // Step 17. (Inlined TemporalDurationFromInternal)
  auto result = duration.date.toDuration();

  // Step 18.
  if (operation == TemporalDifference::Since) {
    result = result.negate();
  }

  // Step 19.
  auto* obj = CreateTemporalDuration(cx, result);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

const char* NonZeroDurationPartAfterMonths(const Duration& duration) {
  if (duration.weeks != 0) {
    return "weeks";
  }
  if (duration.days != 0) {
    return "days";
  }
  if (duration.hours != 0) {
    return "hours";
  }
  if (duration.minutes != 0) {
    return "minutes";
  }
  if (duration.seconds != 0) {
    return "seconds";
  }
  if (duration.milliseconds != 0) {
    return "milliseconds";
  }
  if (duration.microseconds != 0) {
    return "microseconds";
  }
  if (duration.nanoseconds != 0) {
    return "nanoseconds";
  }
  return nullptr;
}

/**
 * AddDurationToYearMonth ( operation, yearMonth, temporalDurationLike, options
 * )
 */

static bool AddDurationToYearMonth(JSContext* cx, TemporalAddDuration operation,
                                   const CallArgs& args) {
  Rooted<PlainYearMonth> yearMonth(
      cx, &args.thisv().toObject().as<PlainYearMonthObject>());

  // Step 1.
  Duration duration;
  if (!ToTemporalDuration(cx, args.get(0), &duration)) {
    return false;
  }

  // Step 2.
  if (operation == TemporalAddDuration::Subtract) {
    duration = duration.negate();
  }

  // Step 3.
  auto internalDuration = ToInternalDurationRecord(duration);

  // Steps 4-5.
  auto overflow = TemporalOverflow::Constrain;
  if (args.hasDefined(1)) {
    // Step 4.
    Rooted<JSObject*> options(
        cx, RequireObjectArg(cx, "options", ToName(operation), args[1]));
    if (!options) {
      return false;
    }

    // Step 5.
    if (!GetTemporalOverflowOption(cx, options, &overflow)) {
      return false;
    }
  }

  // Step 6.
  const auto& durationToAdd = internalDuration.date;

  // Step 7.
  if (durationToAdd.weeks != 0 || durationToAdd.days != 0 ||
      internalDuration.time != TimeDuration{}) {
    JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                              JSMSG_TEMPORAL_PLAIN_YEAR_MONTH_BAD_DURATION,
                              NonZeroDurationPartAfterMonths(duration));
    return false;
  }

  // Step 8.
  auto calendar = yearMonth.calendar();

  // Step 9.
  Rooted<CalendarFields> fields(cx);
  if (!ISODateToFields(cx, yearMonth, &fields)) {
    return false;
  }

  // Step 10.
  MOZ_ASSERT(!fields.has(CalendarField::Day));
  fields.setDay(1);

  // Step 11.
  Rooted<PlainDate> date(cx);
  if (!CalendarDateFromFields(cx, calendar, fields, TemporalOverflow::Constrain,
                              &date)) {
    return false;
  }

  // Step 12.
  ISODate addedDate;
  if (!CalendarDateAdd(cx, calendar, date, durationToAdd, overflow,
                       &addedDate)) {
    return false;
  }
  MOZ_ASSERT(ISODateWithinLimits(addedDate));

  Rooted<PlainYearMonth> addedYearMonth(cx,
                                        PlainYearMonth{addedDate, calendar});

  // Step 13.
  Rooted<CalendarFields> addedDateFields(cx);
  if (!ISODateToFields(cx, addedYearMonth, &addedDateFields)) {
    return false;
  }

  // Step 14.
  Rooted<PlainYearMonth> isoDate(cx);
  if (!CalendarYearMonthFromFields(cx, calendar, addedDateFields, overflow,
                                   &isoDate)) {
    return false;
  }

  // Step 15.
  auto* obj = CreateTemporalYearMonth(cx, isoDate);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

/**
 * Temporal.PlainYearMonth ( isoYear, isoMonth [ , calendar [ , referenceISODay
 * ] ] )
 */

static bool PlainYearMonthConstructor(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);

  // Step 1.
  if (!ThrowIfNotConstructing(cx, args, "Temporal.PlainYearMonth")) {
    return false;
  }

  // Step 3.
  double isoYear;
  if (!ToIntegerWithTruncation(cx, args.get(0), "year", &isoYear)) {
    return false;
  }

  // Step 4.
  double isoMonth;
  if (!ToIntegerWithTruncation(cx, args.get(1), "month", &isoMonth)) {
    return false;
  }

  // Steps 5-7.
  Rooted<CalendarValue> calendar(cx, CalendarValue(CalendarId::ISO8601));
  if (args.hasDefined(2)) {
    // Step 6.
    if (!args[2].isString()) {
      ReportValueError(cx, JSMSG_UNEXPECTED_TYPE, JSDVG_IGNORE_STACK, args[2],
                       nullptr, "not a string");
      return false;
    }

    // Step 7.
    Rooted<JSString*> calendarString(cx, args[2].toString());
    if (!CanonicalizeCalendar(cx, calendarString, &calendar)) {
      return false;
    }
  }

  // Steps 2 and 8.
  double isoDay = 1;
  if (args.hasDefined(3)) {
    if (!ToIntegerWithTruncation(cx, args[3], "day", &isoDay)) {
      return false;
    }
  }

  // Step 9.
  if (!ThrowIfInvalidISODate(cx, isoYear, isoMonth, isoDay)) {
    return false;
  }

  // Step 10.
  auto isoDate = ISODate{int32_t(isoYear), int32_t(isoMonth), int32_t(isoDay)};

  // Step 11.
  auto* yearMonth = CreateTemporalYearMonth(cx, args, isoDate, calendar);
  if (!yearMonth) {
    return false;
  }

  args.rval().setObject(*yearMonth);
  return true;
}

/**
 * Temporal.PlainYearMonth.from ( item [ , options ] )
 */

static bool PlainYearMonth_from(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);

  // Step 1.
  Rooted<PlainYearMonth> yearMonth(cx);
  if (!ToTemporalYearMonth(cx, args.get(0), args.get(1), &yearMonth)) {
    return false;
  }

  auto* result = CreateTemporalYearMonth(cx, yearMonth);
  if (!result) {
    return false;
  }

  args.rval().setObject(*result);
  return true;
}

/**
 * Temporal.PlainYearMonth.compare ( one, two )
 */

static bool PlainYearMonth_compare(JSContext* cx, unsigned argc, Value* vp) {
  CallArgs args = CallArgsFromVp(argc, vp);

  // Step 1.
  Rooted<PlainYearMonth> one(cx);
  if (!ToTemporalYearMonth(cx, args.get(0), &one)) {
    return false;
  }

  // Step 2.
  Rooted<PlainYearMonth> two(cx);
  if (!ToTemporalYearMonth(cx, args.get(1), &two)) {
    return false;
  }

  // Step 3.
  args.rval().setInt32(CompareISODate(one, two));
  return true;
}

/**
 * get Temporal.PlainYearMonth.prototype.calendarId
 */

static bool PlainYearMonth_calendarId(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();

  // Step 3.
  auto* str =
      NewStringCopy<CanGC>(cx, CalendarIdentifier(yearMonth->calendar()));
  if (!str) {
    return false;
  }

  args.rval().setString(str);
  return true;
}

/**
 * get Temporal.PlainYearMonth.prototype.calendarId
 */

static bool PlainYearMonth_calendarId(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_calendarId>(
      cx, args);
}

/**
 * get Temporal.PlainYearMonth.prototype.era
 */

static bool PlainYearMonth_era(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarEra(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.era
 */

static bool PlainYearMonth_era(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_era>(cx, args);
}

/**
 * get Temporal.PlainYearMonth.prototype.eraYear
 */

static bool PlainYearMonth_eraYear(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Steps 3-5.
  return CalendarEraYear(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.eraYear
 */

static bool PlainYearMonth_eraYear(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_eraYear>(cx,
                                                                        args);
}

/**
 * get Temporal.PlainYearMonth.prototype.year
 */

static bool PlainYearMonth_year(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarYear(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.year
 */

static bool PlainYearMonth_year(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_year>(cx, args);
}

/**
 * get Temporal.PlainYearMonth.prototype.month
 */

static bool PlainYearMonth_month(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarMonth(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.month
 */

static bool PlainYearMonth_month(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_month>(cx, args);
}

/**
 * get Temporal.PlainYearMonth.prototype.monthCode
 */

static bool PlainYearMonth_monthCode(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarMonthCode(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.monthCode
 */

static bool PlainYearMonth_monthCode(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_monthCode>(cx,
                                                                          args);
}

/**
 * get Temporal.PlainYearMonth.prototype.daysInYear
 */

static bool PlainYearMonth_daysInYear(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarDaysInYear(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.daysInYear
 */

static bool PlainYearMonth_daysInYear(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_daysInYear>(
      cx, args);
}

/**
 * get Temporal.PlainYearMonth.prototype.daysInMonth
 */

static bool PlainYearMonth_daysInMonth(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarDaysInMonth(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.daysInMonth
 */

static bool PlainYearMonth_daysInMonth(JSContext* cx, unsigned argc,
                                       Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_daysInMonth>(
      cx, args);
}

/**
 * get Temporal.PlainYearMonth.prototype.monthsInYear
 */

static bool PlainYearMonth_monthsInYear(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarMonthsInYear(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.monthsInYear
 */

static bool PlainYearMonth_monthsInYear(JSContext* cx, unsigned argc,
                                        Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_monthsInYear>(
      cx, args);
}

/**
 * get Temporal.PlainYearMonth.prototype.inLeapYear
 */

static bool PlainYearMonth_inLeapYear(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  return CalendarInLeapYear(cx, calendar, yearMonth->date(), args.rval());
}

/**
 * get Temporal.PlainYearMonth.prototype.inLeapYear
 */

static bool PlainYearMonth_inLeapYear(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_inLeapYear>(
      cx, args);
}

/**
 * Temporal.PlainYearMonth.prototype.with ( temporalYearMonthLike [ , options ]
 * )
 */

static bool PlainYearMonth_with(JSContext* cx, const CallArgs& args) {
  Rooted<PlainYearMonth> yearMonth(
      cx, &args.thisv().toObject().as<PlainYearMonthObject>());

  // Step 3.
  Rooted<JSObject*> temporalYearMonthLike(
      cx, RequireObjectArg(cx, "temporalYearMonthLike""with", args.get(0)));
  if (!temporalYearMonthLike) {
    return false;
  }
  if (!ThrowIfTemporalLikeObject(cx, temporalYearMonthLike)) {
    return false;
  }

  // Step 4.
  auto calendar = yearMonth.calendar();

  // Step 5.
  Rooted<CalendarFields> fields(cx);
  if (!ISODateToFields(cx, yearMonth, &fields)) {
    return false;
  }

  // Step 6.
  Rooted<CalendarFields> partialYearMonth(cx);
  if (!PreparePartialCalendarFields(cx, calendar, temporalYearMonthLike,
                                    {
                                        CalendarField::Year,
                                        CalendarField::Month,
                                        CalendarField::MonthCode,
                                    },
                                    &partialYearMonth)) {
    return false;
  }
  MOZ_ASSERT(!partialYearMonth.keys().isEmpty());

  // Step 7.
  fields = CalendarMergeFields(calendar, fields, partialYearMonth);

  // Steps 8-9.
  auto overflow = TemporalOverflow::Constrain;
  if (args.hasDefined(1)) {
    // Step 8.
    Rooted<JSObject*> options(cx,
                              RequireObjectArg(cx, "options""with", args[1]));
    if (!options) {
      return false;
    }

    // Step 9.
    if (!GetTemporalOverflowOption(cx, options, &overflow)) {
      return false;
    }
  }

  // Step 10.
  Rooted<PlainYearMonth> result(cx);
  if (!CalendarYearMonthFromFields(cx, calendar, fields, overflow, &result)) {
    return false;
  }

  // Step 11.
  auto* obj = CreateTemporalYearMonth(cx, result);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

/**
 * Temporal.PlainYearMonth.prototype.with ( temporalYearMonthLike [ , options ]
 * )
 */

static bool PlainYearMonth_with(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_with>(cx, args);
}

/**
 * Temporal.PlainYearMonth.prototype.add ( temporalDurationLike [ , options ] )
 */

static bool PlainYearMonth_add(JSContext* cx, const CallArgs& args) {
  // Step 3.
  return AddDurationToYearMonth(cx, TemporalAddDuration::Add, args);
}

/**
 * Temporal.PlainYearMonth.prototype.add ( temporalDurationLike [ , options ] )
 */

static bool PlainYearMonth_add(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_add>(cx, args);
}

/**
 * Temporal.PlainYearMonth.prototype.subtract ( temporalDurationLike [ , options
 * ] )
 */

static bool PlainYearMonth_subtract(JSContext* cx, const CallArgs& args) {
  // Step 3.
  return AddDurationToYearMonth(cx, TemporalAddDuration::Subtract, args);
}

/**
 * Temporal.PlainYearMonth.prototype.subtract ( temporalDurationLike [ , options
 * ] )
 */

static bool PlainYearMonth_subtract(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_subtract>(cx,
                                                                         args);
}

/**
 * Temporal.PlainYearMonth.prototype.until ( other [ , options ] )
 */

static bool PlainYearMonth_until(JSContext* cx, const CallArgs& args) {
  // Step 3.
  return DifferenceTemporalPlainYearMonth(cx, TemporalDifference::Until, args);
}

/**
 * Temporal.PlainYearMonth.prototype.until ( other [ , options ] )
 */

static bool PlainYearMonth_until(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_until>(cx, args);
}

/**
 * Temporal.PlainYearMonth.prototype.since ( other [ , options ] )
 */

static bool PlainYearMonth_since(JSContext* cx, const CallArgs& args) {
  // Step 3.
  return DifferenceTemporalPlainYearMonth(cx, TemporalDifference::Since, args);
}

/**
 * Temporal.PlainYearMonth.prototype.since ( other [ , options ] )
 */

static bool PlainYearMonth_since(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_since>(cx, args);
}

/**
 * Temporal.PlainYearMonth.prototype.equals ( other )
 */

static bool PlainYearMonth_equals(JSContext* cx, const CallArgs& args) {
  auto* yearMonth = &args.thisv().toObject().as<PlainYearMonthObject>();
  auto date = yearMonth->date();
  Rooted<CalendarValue> calendar(cx, yearMonth->calendar());

  // Step 3.
  Rooted<PlainYearMonth> other(cx);
  if (!ToTemporalYearMonth(cx, args.get(0), &other)) {
    return false;
  }

  // Steps 4-7.
  bool equals =
      date == other.date() && CalendarEquals(calendar, other.calendar());

  args.rval().setBoolean(equals);
  return true;
}

/**
 * Temporal.PlainYearMonth.prototype.equals ( other )
 */

static bool PlainYearMonth_equals(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_equals>(cx,
                                                                       args);
}

/**
 * Temporal.PlainYearMonth.prototype.toString ( [ options ] )
 */

static bool PlainYearMonth_toString(JSContext* cx, const CallArgs& args) {
  Rooted<PlainYearMonthObject*> yearMonth(
      cx, &args.thisv().toObject().as<PlainYearMonthObject>());

  auto showCalendar = ShowCalendar::Auto;
  if (args.hasDefined(0)) {
    // Step 3.
    Rooted<JSObject*> options(
        cx, RequireObjectArg(cx, "options""toString", args[0]));
    if (!options) {
      return false;
    }

    // Step 4.
    if (!GetTemporalShowCalendarNameOption(cx, options, &showCalendar)) {
      return false;
    }
  }

  // Step 5.
  JSString* str = TemporalYearMonthToString(cx, yearMonth, showCalendar);
  if (!str) {
    return false;
  }

  args.rval().setString(str);
  return true;
}

/**
 * Temporal.PlainYearMonth.prototype.toString ( [ options ] )
 */

static bool PlainYearMonth_toString(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_toString>(cx,
                                                                         args);
}

/**
 * Temporal.PlainYearMonth.prototype.toLocaleString ( [ locales [ , options ] ]
 * )
 */

static bool PlainYearMonth_toLocaleString(JSContext* cx, const CallArgs& args) {
  // Steps 3-4.
  return intl::TemporalObjectToLocaleString(cx, args,
                                            intl::DateTimeFormatKind::Date);
}

/**
 * Temporal.PlainYearMonth.prototype.toLocaleString ( [ locales [ , options ] ]
 * )
 */

static bool PlainYearMonth_toLocaleString(JSContext* cx, unsigned argc,
                                          Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_toLocaleString>(
      cx, args);
}

/**
 * Temporal.PlainYearMonth.prototype.toJSON ( )
 */

static bool PlainYearMonth_toJSON(JSContext* cx, const CallArgs& args) {
  Rooted<PlainYearMonthObject*> yearMonth(
      cx, &args.thisv().toObject().as<PlainYearMonthObject>());

  // Step 3.
  JSString* str = TemporalYearMonthToString(cx, yearMonth, ShowCalendar::Auto);
  if (!str) {
    return false;
  }

  args.rval().setString(str);
  return true;
}

/**
 * Temporal.PlainYearMonth.prototype.toJSON ( )
 */

static bool PlainYearMonth_toJSON(JSContext* cx, unsigned argc, Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_toJSON>(cx,
                                                                       args);
}

/**
 *  Temporal.PlainYearMonth.prototype.valueOf ( )
 */

static bool PlainYearMonth_valueOf(JSContext* cx, unsigned argc, Value* vp) {
  JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
                            "PlainYearMonth""primitive type");
  return false;
}

/**
 * Temporal.PlainYearMonth.prototype.toPlainDate ( item )
 */

static bool PlainYearMonth_toPlainDate(JSContext* cx, const CallArgs& args) {
  Rooted<PlainYearMonth> yearMonth(
      cx, &args.thisv().toObject().as<PlainYearMonthObject>());

  // Step 3.
  Rooted<JSObject*> item(
      cx, RequireObjectArg(cx, "item""toPlainDate", args.get(0)));
  if (!item) {
    return false;
  }

  // Step 4.
  auto calendar = yearMonth.calendar();

  // Step 5.
  Rooted<CalendarFields> fields(cx);
  if (!ISODateToFields(cx, yearMonth, &fields)) {
    return false;
  }

  // Step 6.
  Rooted<CalendarFields> inputFields(cx);
  if (!PrepareCalendarFields(cx, calendar, item,
                             {
                                 CalendarField::Day,
                             },
                             &inputFields)) {
    return false;
  }

  // Step 7.
  fields = CalendarMergeFields(calendar, fields, inputFields);

  // Step 8.
  Rooted<PlainDate> result(cx);
  if (!CalendarDateFromFields(cx, calendar, fields, TemporalOverflow::Constrain,
                              &result)) {
    return false;
  }

  // Step 9.
  auto* obj = CreateTemporalDate(cx, result);
  if (!obj) {
    return false;
  }

  args.rval().setObject(*obj);
  return true;
}

/**
 * Temporal.PlainYearMonth.prototype.toPlainDate ( item )
 */

static bool PlainYearMonth_toPlainDate(JSContext* cx, unsigned argc,
                                       Value* vp) {
  // Steps 1-2.
  CallArgs args = CallArgsFromVp(argc, vp);
  return CallNonGenericMethod<IsPlainYearMonth, PlainYearMonth_toPlainDate>(
      cx, args);
}

const JSClass PlainYearMonthObject::class_ = {
    "Temporal.PlainYearMonth",
    JSCLASS_HAS_RESERVED_SLOTS(PlainYearMonthObject::SLOT_COUNT) |
        JSCLASS_HAS_CACHED_PROTO(JSProto_PlainYearMonth),
    JS_NULL_CLASS_OPS,
    &PlainYearMonthObject::classSpec_,
};

const JSClass& PlainYearMonthObject::protoClass_ = PlainObject::class_;

static const JSFunctionSpec PlainYearMonth_methods[] = {
    JS_FN("from", PlainYearMonth_from, 10),
    JS_FN("compare", PlainYearMonth_compare, 20),
    JS_FS_END,
};

static const JSFunctionSpec PlainYearMonth_prototype_methods[] = {
    JS_FN("with", PlainYearMonth_with, 10),
    JS_FN("add", PlainYearMonth_add, 10),
    JS_FN("subtract", PlainYearMonth_subtract, 10),
    JS_FN("until", PlainYearMonth_until, 10),
    JS_FN("since", PlainYearMonth_since, 10),
    JS_FN("equals", PlainYearMonth_equals, 10),
    JS_FN("toString", PlainYearMonth_toString, 00),
    JS_FN("toLocaleString", PlainYearMonth_toLocaleString, 00),
    JS_FN("toJSON", PlainYearMonth_toJSON, 00),
    JS_FN("valueOf", PlainYearMonth_valueOf, 00),
    JS_FN("toPlainDate", PlainYearMonth_toPlainDate, 10),
    JS_FS_END,
};

static const JSPropertySpec PlainYearMonth_prototype_properties[] = {
    JS_PSG("calendarId", PlainYearMonth_calendarId, 0),
    JS_PSG("era", PlainYearMonth_era, 0),
    JS_PSG("eraYear", PlainYearMonth_eraYear, 0),
    JS_PSG("year", PlainYearMonth_year, 0),
    JS_PSG("month", PlainYearMonth_month, 0),
    JS_PSG("monthCode", PlainYearMonth_monthCode, 0),
    JS_PSG("daysInYear", PlainYearMonth_daysInYear, 0),
    JS_PSG("daysInMonth", PlainYearMonth_daysInMonth, 0),
    JS_PSG("monthsInYear", PlainYearMonth_monthsInYear, 0),
    JS_PSG("inLeapYear", PlainYearMonth_inLeapYear, 0),
    JS_STRING_SYM_PS(toStringTag, "Temporal.PlainYearMonth", JSPROP_READONLY),
    JS_PS_END,
};

const ClassSpec PlainYearMonthObject::classSpec_ = {
    GenericCreateConstructor<PlainYearMonthConstructor, 2,
                             gc::AllocKind::FUNCTION>,
    GenericCreatePrototype<PlainYearMonthObject>,
    PlainYearMonth_methods,
    nullptr,
    PlainYearMonth_prototype_methods,
    PlainYearMonth_prototype_properties,
    nullptr,
    ClassSpec::DontDefineConstructor,
};

Messung V0.5 in Prozent
C=88 H=99 G=93

¤ Dauer der Verarbeitung: 0.19 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002