return a < b ? a : b;
}
-JSValue js_create_duration(JSContext *ctx, const JSDurationData *d)
+static JSValue js_create_duration2(JSContext *ctx, JSValueConst new_target, const JSDurationData *d)
{
JSDurationData *s;
JSValue obj;
*s = *d;
/* Round fields to float64-representable integers to match spec behavior */
duration_round_fields_to_float64(s);
- obj = JS_NewObjectClass(ctx, (int)js_duration_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_duration_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
return obj;
}
+JSValue js_create_duration(JSContext *ctx, const JSDurationData *d)
+{
+ return js_create_duration2(ctx, JS_UNDEFINED, d);
+}
+
static int to_integer_if_integral(JSContext *ctx, JSValueConst val, int64_t *pres)
{
double d;
{
JSDurationData d = {0};
js_int128_t tmp_microseconds = 0, tmp_nanoseconds = 0;
- JSValue obj;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.Duration constructor cannot be called as a function");
- }
if (argc > 0 && to_integer_if_integral(ctx, argv[0], &d.years) < 0)
return JS_EXCEPTION;
if (argc > 1 && to_integer_if_integral(ctx, argv[1], &d.months) < 0)
return JS_ThrowRangeError(ctx, "duration out of range");
if (duration_is_out_of_range(&d))
return JS_ThrowRangeError(ctx, "duration out of range");
- {
- JSDurationData *s = js_mallocz(ctx, sizeof(*s));
- if (!s)
- return JS_EXCEPTION;
- *s = d;
- obj = js_create_temporal_object(ctx, new_target, js_duration_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
- return JS_EXCEPTION;
- }
- return obj;
- }
+ return js_create_duration2(ctx, new_target, &d);
}
/* Temporal.Duration.from */
.finalizer = js_instant_finalizer,
};
-JSValue js_create_instant(JSContext *ctx, const JSTimeSpec *ts)
+static JSValue js_create_instant2(JSContext *ctx, JSValueConst new_target, const JSTimeSpec *ts)
{
JSInstantData *s;
JSValue obj;
+ if (!is_valid_epoch_timespec(ts))
+ return JS_ThrowRangeError(ctx, "epochNanoseconds out of range");
s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
s->ts = *ts;
- obj = JS_NewObjectClass(ctx, (int)js_instant_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_instant_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
return obj;
}
+JSValue js_create_instant(JSContext *ctx, const JSTimeSpec *ts)
+{
+ return js_create_instant2(ctx, JS_UNDEFINED, ts);
+}
+
/* --- Date math helpers --- */
static int ti_is_leap_year(int64_t y)
static JSValue js_instant_constructor(JSContext *ctx, JSValueConst new_target,
int argc, JSValueConst *argv)
{
- (void)argc;
- JSValue obj = JS_UNDEFINED;
JSTimeSpec ts;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.Instant constructor cannot be called as a function");
- }
if (JS_IsUndefined(argv[0])) {
return JS_ThrowTypeError(ctx, "Temporal.Instant requires an epochNanoseconds argument");
}
if (ti_bigint_to_timespec(ctx, argv[0], &ts) < 0)
return JS_EXCEPTION;
- if (!is_valid_epoch_timespec(&ts)) {
- return JS_ThrowRangeError(ctx, "epochNanoseconds out of range");
- }
- {
- JSInstantData *s = js_mallocz(ctx, sizeof(*s));
- if (!s)
- return JS_EXCEPTION;
- s->ts = ts;
- obj = js_create_temporal_object(ctx, new_target, js_instant_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
- return JS_EXCEPTION;
- }
- return obj;
- }
+ return js_create_instant2(ctx, new_target, &ts);
}
/* Temporal.Instant.fromEpochMilliseconds */
if (js_number_to_int64(ctx, val, &ms) < 0)
return JS_EXCEPTION;
ms_to_timespec(ms, &ts);
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "epochMilliseconds out of range");
return js_create_instant(ctx, &ts);
}
JSTimeSpec ts;
if (ti_bigint_to_timespec(ctx, argv[0], &ts) < 0)
return JS_EXCEPTION;
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "epochNanoseconds out of range");
return js_create_instant(ctx, &ts);
}
/* Convert back to JSTimeSpec */
ti_ns_to_timespec(rounded_ns, &result);
- if (!is_valid_epoch_timespec(&result))
- return JS_ThrowRangeError(ctx, "rounded value out of range");
return js_create_instant(ctx, &result);
}
total_ns = -total_ns;
total_ns += ti_timespec_to_ns(&s->ts);
-
- if (total_ns < (js_int128_t)(-INSTANT_MAX_SECS) * 1000000000 ||
- total_ns > (js_int128_t)INSTANT_MAX_SECS * 1000000000)
- return JS_ThrowRangeError(ctx, "instant arithmetic overflow");
-
ti_ns_to_timespec(total_ns, &result);
return js_create_instant(ctx, &result);
}
.finalizer = js_plaindate_finalizer,
};
-JSValue js_create_plaindate_with_calendar(JSContext *ctx, int year, int month, int day, CalendarType calendar)
+static JSValue js_create_plaindate_with_calendar2(JSContext *ctx, JSValueConst new_target, int year, int month, int day, CalendarType calendar)
{
- if (calendar == CAL_ISO8601 || calendar == CAL_GREGORY) {
- /* ISO date range: -271821-04-19 to +275760-09-13 */
- if (year < -271821 || year > 275760 ||
- (year == -271821 && (month < 4 || (month == 4 && day < 19))) ||
- (year == 275760 && (month > 9 || (month == 9 && day > 13))))
- return JS_ThrowRangeError(ctx, "PlainDate out of range");
- }
+ if (!ti_is_date_within_iso_limits(year, month, day))
+ return JS_ThrowRangeError(ctx, "PlainDate out of range");
{
JSPlainDateData *s;
JSValue obj;
s->month = month;
s->day = day;
s->calendar = calendar;
- obj = JS_NewObjectClass(ctx, (int)js_plaindate_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_plaindate_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
}
}
+JSValue js_create_plaindate_with_calendar(JSContext *ctx, int year, int month, int day, CalendarType calendar)
+{
+ return js_create_plaindate_with_calendar2(ctx, JS_UNDEFINED, year, month, day, calendar);
+}
+
JSValue js_create_plaindate(JSContext *ctx, int year, int month, int day)
{
return js_create_plaindate_with_calendar(ctx, year, month, day, CAL_ISO8601);
JSValue ti_create_plaindate_from_fields(JSContext *ctx, TIPreparedFields *fields,
int overflow_constrain)
{
- int year, month, day;
- JSValue obj;
+ int year, month, day, iso_y, iso_m, iso_d;
if (ti_resolve_date_from_fields(ctx, fields, overflow_constrain, &year, &month, &day, 1) < 0)
return JS_EXCEPTION;
-
- {
- int iso_y = year, iso_m = month, iso_d = day;
- if (fields->calendar != CAL_ISO8601 && fields->calendar != CAL_GREGORY) {
- ti_calendar_date_to_iso(fields->calendar, year, month, day, &iso_y, &iso_m, &iso_d);
- }
- obj = js_create_plaindate_with_calendar(ctx, iso_y, iso_m, iso_d, fields->calendar);
- }
- return obj;
+ ti_calendar_date_to_iso(fields->calendar, year, month, day, &iso_y, &iso_m, &iso_d);
+ return js_create_plaindate_with_calendar(ctx, iso_y, iso_m, iso_d, fields->calendar);
}
int pd_is_leap_year(int year)
int pd_days_in_month(int year, int month)
{
static const int days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
+ if (month < 1 || month > 12)
+ return 30; /* fail safe */
if (month == 2 && pd_is_leap_year(year))
return 29;
return days[month - 1];
int argc, JSValueConst *argv)
{
int year, month, day;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.PlainDate constructor cannot be called as a function");
- }
+ CalendarType calendar = CAL_ISO8601;
if (pd_to_integer_with_truncation(ctx, argv[0], &year) < 0)
return JS_EXCEPTION;
if (pd_to_integer_with_truncation(ctx, argv[1], &month) < 0)
return JS_EXCEPTION;
if (!pd_is_valid_date(year, month, day))
return JS_ThrowRangeError(ctx, "invalid PlainDate");
- if (year < -271821 || year > 275760 ||
- (year == -271821 && (month < 4 || (month == 4 && day < 19))) ||
- (year == 275760 && (month > 9 || (month == 9 && day > 13))))
- return JS_ThrowRangeError(ctx, "PlainDate out of range");
- {
- JSPlainDateData *s = js_mallocz(ctx, sizeof(*s));
- JSValue obj;
- if (!s)
- return JS_EXCEPTION;
- s->year = year;
- s->month = month;
- s->day = day;
- s->calendar = CAL_ISO8601;
- if (argc > 3) {
- int cal_res = ti_validate_constructor_calendar(ctx, argv[3], &s->calendar);
- if (cal_res < 0) {
- js_free(ctx, s);
- return JS_EXCEPTION;
- }
- }
- obj = js_create_temporal_object(ctx, new_target, js_plaindate_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
+ calendar = CAL_ISO8601;
+ if (argc > 3) {
+ if (ti_validate_constructor_calendar(ctx, argv[3], &calendar) < 0)
return JS_EXCEPTION;
- }
- return obj;
}
+ return js_create_plaindate_with_calendar2(ctx, new_target, year, month, day, calendar);
}
/* Getters */
ti_calendar_date_to_iso(s->calendar, year, month, day, &iso_y, &iso_m, &iso_d);
year = iso_y; month = iso_m; day = iso_d;
}
- if (year < -271821 || year > 275760)
- return JS_ThrowRangeError(ctx, "invalid PlainDate");
- /* Check against ISO date bounds */
- if (year == -271821 && (month < 4 || (month == 4 && day < 19)))
- return JS_ThrowRangeError(ctx, "invalid PlainDate");
- if (year == 275760 && (month > 9 || (month == 9 && day > 13)))
- return JS_ThrowRangeError(ctx, "invalid PlainDate");
- {
- JSValue obj = js_create_plaindate_with_calendar(ctx, year, month, day, s->calendar);
- return obj;
- }
+ return js_create_plaindate_with_calendar(ctx, year, month, day, s->calendar);
}
static JSValue js_plaindate_difference(JSContext *ctx, JSValueConst this_val,
}
}
}
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "epoch nanoseconds outside valid limits");
return js_create_zoneddatetime(ctx, &ts, timeZone, s->calendar);
}
millisecond, microsecond, nanosecond, CAL_ISO8601);
}
-JSValue js_create_plaindatetime_with_calendar(JSContext *ctx, int year, int month, int day,
- int hour, int minute, int second,
- int millisecond, int microsecond, int nanosecond,
- CalendarType calendar)
+static JSValue js_create_plaindatetime_with_calendar2(JSContext *ctx, JSValueConst new_target, int year, int month, int day,
+ int hour, int minute, int second,
+ int millisecond, int microsecond, int nanosecond,
+ CalendarType calendar)
{
JSPlainDateTimeData *s;
JSValue obj;
- if ((calendar == CAL_ISO8601 || calendar == CAL_GREGORY) &&
- !pdt_is_within_limits(year, month, day, hour, minute, second,
- millisecond, microsecond, nanosecond))
+ if (!pdt_is_within_limits(year, month, day, hour, minute, second,
+ millisecond, microsecond, nanosecond)) {
return JS_ThrowRangeError(ctx, "PlainDateTime outside valid ISO range");
+ }
s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
s->microsecond = microsecond;
s->nanosecond = nanosecond;
s->calendar = calendar;
- obj = JS_NewObjectClass(ctx, (int)js_plaindatetime_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_plaindatetime_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
return obj;
}
+JSValue js_create_plaindatetime_with_calendar(JSContext *ctx, int year, int month, int day,
+ int hour, int minute, int second,
+ int millisecond, int microsecond, int nanosecond,
+ CalendarType calendar)
+{
+ return js_create_plaindatetime_with_calendar2(ctx, JS_UNDEFINED, year, month, day, hour, minute, second,
+ millisecond, microsecond, nanosecond, calendar);
+}
+
static JSValue ti_create_plaindatetime_from_fields(JSContext *ctx, TIPreparedFields *fields,
int overflow_constrain)
{
if (ns > 999) ns = 999; else if (ns < 0) ns = 0;
}
- if (fields->calendar != CAL_ISO8601 && fields->calendar != CAL_GREGORY) {
+ {
int iso_y, iso_m, iso_d;
ti_calendar_date_to_iso(fields->calendar, year, month, day, &iso_y, &iso_m, &iso_d);
year = iso_y; month = iso_m; day = iso_d;
{
int year, month, day, hour = 0, minute = 0, second = 0;
int millisecond = 0, microsecond = 0, nanosecond = 0;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.PlainDateTime constructor cannot be called as a function");
- }
+ CalendarType calendar = CAL_ISO8601;
if (JS_IsUndefined(argv[0])) {
JS_ThrowRangeError(ctx, "value must be an integer");
return JS_EXCEPTION;
return JS_ThrowRangeError(ctx, "invalid PlainDateTime date");
if (!pdt_is_valid_time(hour, minute, second, millisecond, microsecond, nanosecond))
return JS_ThrowRangeError(ctx, "invalid PlainDateTime time");
- {
- CalendarType calendar = CAL_ISO8601;
- if (argc > 9) {
- int cal_res = ti_validate_constructor_calendar(ctx, argv[9], &calendar);
- if (cal_res < 0)
- return JS_EXCEPTION;
- }
- if ((calendar == CAL_ISO8601 || calendar == CAL_GREGORY) &&
- !pdt_is_within_limits(year, month, day, hour, minute, second,
- millisecond, microsecond, nanosecond))
- return JS_ThrowRangeError(ctx, "PlainDateTime outside valid range");
- {
- JSPlainDateTimeData *s = js_mallocz(ctx, sizeof(*s));
- JSValue obj;
- if (!s)
- return JS_EXCEPTION;
- s->year = year;
- s->month = month;
- s->day = day;
- s->hour = hour;
- s->minute = minute;
- s->second = second;
- s->millisecond = millisecond;
- s->microsecond = microsecond;
- s->nanosecond = nanosecond;
- s->calendar = calendar;
- obj = js_create_temporal_object(ctx, new_target, js_plaindatetime_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
+ if (argc > 9) {
+ int cal_res = ti_validate_constructor_calendar(ctx, argv[9], &calendar);
+ if (cal_res < 0)
return JS_EXCEPTION;
- }
- return obj;
- }
}
+ return js_create_plaindatetime_with_calendar2(ctx, new_target, year, month, day, hour, minute, second,
+ millisecond, microsecond, nanosecond, calendar);
}
/* Getters */
ti_calendar_date_to_iso(s->calendar, year, month, day, &iso_y, &iso_m, &iso_d);
year = iso_y; month = iso_m; day = iso_d;
}
- if (!pdt_is_within_limits(year, month, day, hour, minute, second,
- millisecond, microsecond, nanosecond))
- return JS_ThrowRangeError(ctx, "PlainDateTime outside valid range");
return js_create_plaindatetime_with_calendar(ctx, year, month, day, hour, minute, second,
millisecond, microsecond, nanosecond, s->calendar);
}
}
}
}
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "epoch nanoseconds outside valid limits");
return js_create_zoneddatetime(ctx, &ts, timeZone, s->calendar);
}
}
.finalizer = js_plainmonthday_finalizer,
};
-JSValue js_create_plainmonthday_with_calendar(JSContext *ctx, int iso_year, int iso_month, int iso_day, CalendarType calendar)
+static JSValue js_create_plainmonthday_with_calendar2(JSContext *ctx, JSValueConst new_target, int iso_year, int iso_month, int iso_day, CalendarType calendar)
{
JSPlainMonthDayData *s;
JSValue obj;
- /* Validate ISO year range (ISO date limits: -271821 to 275760) */
- if (iso_year < -271821 || iso_year > 275760)
+ if (!ti_is_date_within_iso_limits(iso_year, iso_month, iso_day))
return JS_ThrowRangeError(ctx, "PlainMonthDay out of range");
s = js_mallocz(ctx, sizeof(*s));
if (!s)
s->iso_month = iso_month;
s->iso_day = iso_day;
s->calendar = calendar;
- obj = JS_NewObjectClass(ctx, (int)js_plainmonthday_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_plainmonthday_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
return obj;
}
+JSValue js_create_plainmonthday_with_calendar(JSContext *ctx, int iso_year, int iso_month, int iso_day, CalendarType calendar)
+{
+ return js_create_plainmonthday_with_calendar2(ctx, JS_UNDEFINED, iso_year, iso_month, iso_day, calendar);
+}
+
static int pmd_to_integer_with_truncation(JSContext *ctx, JSValueConst val, int *pres)
{
double d;
int argc, JSValueConst *argv)
{
int month, day, year = 1972;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.PlainMonthDay constructor cannot be called as a function");
- }
if (pmd_to_integer_with_truncation(ctx, argv[0], &month) < 0)
return JS_EXCEPTION;
if (pmd_to_integer_with_truncation(ctx, argv[1], &day) < 0)
}
if (month < 1 || month > 12 || day < 1 || day > pd_days_in_month(year, month))
return JS_ThrowRangeError(ctx, "invalid PlainMonthDay");
- /* ISODateWithinLimits check for CreateTemporalMonthDay */
- if (year < -271821 || (year == -271821 && (month < 4 || (month == 4 && day < 19))))
- return JS_ThrowRangeError(ctx, "date outside supported range");
- if (year > 275760 || (year == 275760 && (month > 9 || (month == 9 && day > 13))))
- return JS_ThrowRangeError(ctx, "date outside supported range");
- {
- JSPlainMonthDayData *s = js_mallocz(ctx, sizeof(*s));
- JSValue obj;
- if (!s)
- return JS_EXCEPTION;
- s->iso_year = year;
- s->iso_month = month;
- s->iso_day = day;
- s->calendar = calendar;
- obj = js_create_temporal_object(ctx, new_target, js_plainmonthday_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
- return JS_EXCEPTION;
- }
- return obj;
- }
+ return js_create_plainmonthday_with_calendar2(ctx, new_target, year, month, day, calendar);
}
}
return JS_ThrowRangeError(ctx, "month and monthCode must agree");
{
int ref_year = has_year ? year_for_overflow : orig_cal_y;
+ int max_month = ti_calendar_months_in_year(s->calendar, ref_year);
+
+ if (month < 1 || month > max_month) {
+ if (!overflow_constrain)
+ return JS_ThrowRangeError(ctx, "invalid PlainMonthDay");
+ if (month > max_month)
+ month = max_month;
+ else if (month < 1)
+ month = 1;
+ }
+
int dim = ti_calendar_days_in_month(s->calendar, ref_year, month);
if (day > dim || day < 1) {
if (!overflow_constrain)
.finalizer = js_plaintime_finalizer,
};
-JSValue js_create_plaintime(JSContext *ctx, const JSPlainTimeData *t)
+static JSValue js_create_plaintime2(JSContext *ctx, JSValueConst new_target, const JSPlainTimeData *t)
{
JSPlainTimeData *s;
JSValue obj;
if (!s)
return JS_EXCEPTION;
*s = *t;
- obj = JS_NewObjectClass(ctx, (int)js_plaintime_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_plaintime_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
return obj;
}
+JSValue js_create_plaintime(JSContext *ctx, const JSPlainTimeData *t)
+{
+ return js_create_plaintime2(ctx, JS_UNDEFINED, t);
+}
+
/* Forward declaration */
JSValue js_plaintime_from(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv);
int argc, JSValueConst *argv)
{
JSPlainTimeData t = {0};
- JSValue obj;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.PlainTime constructor cannot be called as a function");
- }
if (argc > 0 && pt_to_integer_with_truncation(ctx, argv[0], &t.hour) < 0)
return JS_EXCEPTION;
if (argc > 1 && pt_to_integer_with_truncation(ctx, argv[1], &t.minute) < 0)
return JS_EXCEPTION;
if (!pt_is_valid_time(t.hour, t.minute, t.second, t.millisecond, t.microsecond, t.nanosecond))
return JS_ThrowRangeError(ctx, "invalid PlainTime");
- {
- JSPlainTimeData *s = js_mallocz(ctx, sizeof(*s));
- if (!s)
- return JS_EXCEPTION;
- *s = t;
- obj = js_create_temporal_object(ctx, new_target, js_plaintime_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
- return JS_EXCEPTION;
- }
- return obj;
- }
+ return js_create_plaintime2(ctx, new_target, &t);
}
/* Getters */
.finalizer = js_plainyearmonth_finalizer,
};
-static JSValue js_create_plainyearmonth(JSContext *ctx, int year, int month, int referenceISODay)
+static int pym_is_valid_year_month(int year, int month)
{
- return js_create_plainyearmonth_with_calendar(ctx, year, month, referenceISODay, CAL_ISO8601);
+ return month >= 1 && month <= 12 &&
+ ((year > -271821 || (year == -271821 && month >= 4)) &&
+ (year < 275760 || (year == 275760 && month <= 9)));
}
-JSValue js_create_plainyearmonth_with_calendar(JSContext *ctx, int year, int month, int referenceISODay, CalendarType calendar)
+static JSValue js_create_plainyearmonth_with_calendar2(JSContext *ctx, JSValueConst new_target, int year, int month, int referenceISODay, CalendarType calendar)
{
JSPlainYearMonthData *s;
JSValue obj;
+ /* XXX: test the day too ? */
+ if (!pym_is_valid_year_month(year, month))
+ return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
s->iso_month = month;
s->iso_day = referenceISODay;
s->calendar = calendar;
- obj = JS_NewObjectClass(ctx, (int)js_plainyearmonth_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_plainyearmonth_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
return obj;
}
+JSValue js_create_plainyearmonth_with_calendar(JSContext *ctx, int year, int month, int referenceISODay, CalendarType calendar)
+{
+ return js_create_plainyearmonth_with_calendar2(ctx, JS_UNDEFINED, year, month, referenceISODay, calendar);
+}
+
static JSValue ti_create_plainyearmonth_from_fields(JSContext *ctx, TIPreparedFields *fields,
int overflow_constrain)
{
int year, month, dummy_day = 1;
- JSValue obj;
- JSPlainYearMonthData *s;
if (ti_resolve_date_from_fields(ctx, fields, overflow_constrain, &year, &month, &dummy_day, 0) < 0)
return JS_EXCEPTION;
}
}
- if (fields->calendar == CAL_ISO8601 || fields->calendar == CAL_GREGORY) {
- int is_valid = month >= 1 && month <= 12 &&
- ((year > -271821 || (year == -271821 && month >= 4)) &&
- (year < 275760 || (year == 275760 && month <= 9)));
- if (!is_valid)
- return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
- }
-
{
- int iso_d = 1;
+ int iso_y, iso_m, iso_d = 1;
/* Convert calendar date to ISO for all non-ISO/non-Gregory calendars */
- if (fields->calendar != CAL_ISO8601 && fields->calendar != CAL_GREGORY) {
- int iso_y, iso_m;
- ti_calendar_date_to_iso(fields->calendar, year, month, 1, &iso_y, &iso_m, &iso_d);
- year = iso_y;
- month = iso_m;
- }
- {
- int is_valid = month >= 1 && month <= 12 &&
- ((year > -271821 || (year == -271821 && month >= 4)) &&
- (year < 275760 || (year == 275760 && month <= 9)));
- if (!is_valid)
- return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
- }
- obj = js_create_plainyearmonth(ctx, year, month, iso_d);
- }
- if (!JS_IsException(obj)) {
- s = JS_GetOpaque(obj, js_plainyearmonth_class_id);
- if (s) {
- s->calendar = fields->calendar;
- }
+ ti_calendar_date_to_iso(fields->calendar, year, month, 1, &iso_y, &iso_m, &iso_d);
+ year = iso_y;
+ month = iso_m;
+ return js_create_plainyearmonth_with_calendar(ctx, year, month, iso_d, fields->calendar);
}
- return obj;
-}
-
-static int pym_is_valid_year_month(int year, int month)
-{
- return month >= 1 && month <= 12 &&
- ((year > -271821 || (year == -271821 && month >= 4)) &&
- (year < 275760 || (year == 275760 && month <= 9)));
}
static int pym_to_integer_with_truncation(JSContext *ctx, JSValueConst val, int *pres)
int argc, JSValueConst *argv)
{
int year, month, day = 1;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.PlainYearMonth constructor cannot be called as a function");
- }
if (pym_to_integer_with_truncation(ctx, argv[0], &year) < 0)
return JS_EXCEPTION;
if (pym_to_integer_with_truncation(ctx, argv[1], &month) < 0)
return JS_EXCEPTION;
if (!pym_is_valid_year_month(year, month))
return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
- if (year < -271821 || (year == -271821 && month < 4))
- return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
- if (year > 275760 || (year == 275760 && month > 9))
- return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
{
CalendarType calendar = CAL_ISO8601;
if (argc > 2) {
return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
if (argc <= 3 || JS_IsUndefined(argv[3]))
day = 1;
- {
- JSPlainYearMonthData *s = js_mallocz(ctx, sizeof(*s));
- JSValue obj;
- if (!s)
- return JS_EXCEPTION;
- s->iso_year = year;
- s->iso_month = month;
- s->iso_day = day;
- s->calendar = calendar;
- obj = js_create_temporal_object(ctx, new_target, js_plainyearmonth_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
- return JS_EXCEPTION;
- }
- return obj;
- }
+ return js_create_plainyearmonth_with_calendar2(ctx, new_target, year, month, day, calendar);
}
}
/* Convert ISO to calendar space for arithmetic */
pym_get_calendar_date(s, &cal_year, &cal_month, &cal_day);
/* Check that base date is within ISO limits */
- if (s->iso_year < -271821 || (s->iso_year == -271821 && (s->iso_month < 4 || (s->iso_month == 4 && s->iso_day < 19))))
- return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
- if (s->iso_year > 275760 || (s->iso_year == 275760 && (s->iso_month > 9 || (s->iso_month == 9 && s->iso_day > 13))))
+ if (!ti_is_date_within_iso_limits(s->iso_year, s->iso_month, s->iso_day))
return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
{
int orig_mc = 0, orig_has_l = 0;
{
int iso_y, iso_m, iso_d;
ti_calendar_date_to_iso(s->calendar, cal_year, cal_month, cal_day, &iso_y, &iso_m, &iso_d);
- if (iso_y < -271821 || (iso_y == -271821 && iso_m < 4))
- return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
- if (iso_y > 275760 || (iso_y == 275760 && iso_m > 9))
- return JS_ThrowRangeError(ctx, "invalid PlainYearMonth");
return js_create_plainyearmonth_with_calendar(ctx, iso_y, iso_m, iso_d, s->calendar);
}
}
*out_str = str;
return 1;
}
-JSValue js_create_temporal_object(JSContext *ctx, JSValueConst new_target,
- JSClassID class_id, void *opaque)
-{
-
- JSValue obj = JS_CreateFromConstructor(ctx, new_target, class_id);
- if (JS_IsException(obj))
- return JS_EXCEPTION;
- JS_SetOpaque(obj, opaque);
- return obj;
-}
+
int is_valid_epoch_timespec(const JSTimeSpec *ts)
{
if (ts->secs > INSTANT_MAX_SECS || ts->secs < -INSTANT_MAX_SECS)
int ti_canonicalize_timezone_identifier(const char *str, int64_t offset_ns, char *out, size_t out_size);
int ti_validate_constructor_calendar(JSContext *ctx, JSValueConst v, CalendarType *out);
int ti_validate_timezone_identifier(JSContext *ctx, JSValueConst v, const char **out_str);
-JSValue js_create_temporal_object(JSContext *ctx, JSValueConst new_target, JSClassID class_id, void *opaque);
int is_valid_epoch_timespec(const JSTimeSpec *ts);
static inline js_int128_t ti_sec_nsec_to_ns(int64_t secs, uint32_t nsecs)
.finalizer = js_zoneddatetime_finalizer,
};
-JSValue js_create_zoneddatetime(JSContext *ctx, const JSTimeSpec *ts,
+static JSValue js_create_zoneddatetime2(JSContext *ctx, JSValueConst new_target, const JSTimeSpec *ts,
const char *timeZone, CalendarType calendar)
{
JSZonedDateTimeData *s;
JSValue obj;
+ if (!is_valid_epoch_timespec(ts))
+ return JS_ThrowRangeError(ctx, "epoch nanoseconds outside valid limits");
s = js_mallocz(ctx, sizeof(*s));
if (!s)
return JS_EXCEPTION;
s->ts = *ts;
pstrcpy(s->timeZone, sizeof(s->timeZone), timeZone);
s->calendar = calendar;
- obj = JS_NewObjectClass(ctx, (int)js_zoneddatetime_class_id);
+ obj = JS_CreateFromConstructor(ctx, new_target, js_zoneddatetime_class_id);
if (JS_IsException(obj)) {
js_free(ctx, s);
return JS_EXCEPTION;
return obj;
}
+JSValue js_create_zoneddatetime(JSContext *ctx, const JSTimeSpec *ts,
+ const char *timeZone, CalendarType calendar)
+{
+ return js_create_zoneddatetime2(ctx, JS_UNDEFINED, ts, timeZone, calendar);
+}
+
/* Apply timezone offset to UTC epoch seconds to get local wall-clock time */
/* Create a ZonedDateTime from prepared fields */
JSValue ti_create_zoneddatetime_from_fields(JSContext *ctx, TIPreparedFields *fields,
}
}
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "epoch nanoseconds outside valid limits");
-
return js_create_zoneddatetime(ctx, &ts, timeZone, fields->calendar);
}
static void zdt_apply_timezone_offset(JSContext *ctx, JSZonedDateTimeData *s,
static JSValue js_zoneddatetime_constructor(JSContext *ctx, JSValueConst new_target,
int argc, JSValueConst *argv)
{
- JSZonedDateTimeData *s;
JSValue obj;
JSTimeSpec ts;
const char *timeZone = "UTC";
CalendarType calendar = CAL_ISO8601;
int tz_allocated = 0;
- if (JS_IsUndefined(new_target)) {
- return JS_ThrowTypeError(ctx, "Temporal.ZonedDateTime constructor cannot be called as a function");
- }
if (ti_bigint_to_timespec(ctx, argv[0], &ts) < 0)
return JS_EXCEPTION;
if (!is_valid_epoch_timespec(&ts))
return JS_EXCEPTION;
}
}
- s = js_mallocz(ctx, sizeof(*s));
- if (!s) {
- if (tz_allocated) JS_FreeCString(ctx, timeZone);
- return JS_EXCEPTION;
- }
- s->ts = ts;
- pstrcpy(s->timeZone, sizeof(s->timeZone), timeZone);
- s->calendar = calendar;
- obj = js_create_temporal_object(ctx, new_target, js_zoneddatetime_class_id, s);
- if (JS_IsException(obj)) {
- js_free(ctx, s);
- if (tz_allocated) JS_FreeCString(ctx, timeZone);
- return JS_EXCEPTION;
- }
+ obj = js_create_zoneddatetime2(ctx, new_target, &ts, timeZone, calendar);
if (tz_allocated) JS_FreeCString(ctx, timeZone);
return obj;
}
} else {
ts.secs -= offset_sec;
}
- /* Validate epoch nanoseconds are within Instant limits */
- {
- js_int128_t epoch_ns = ti_timespec_to_ns(&ts);
- js_int128_t limit = (js_int128_t)8640000000000LL * 1000000000LL;
- if (epoch_ns < -limit || epoch_ns > limit)
- return JS_ThrowRangeError(ctx, "epoch nanoseconds outside valid limits");
- }
return js_create_zoneddatetime(ctx, &ts, s->timeZone, s->calendar);
}
ti_ns_to_timespec(rounded_ns, &result);
- if (!is_valid_epoch_timespec(&result))
- return JS_ThrowRangeError(ctx, "outside representable range");
return js_create_zoneddatetime(ctx, &result, s->timeZone, s->calendar);
}
}
}
}
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "epoch nanoseconds outside valid limits");
return js_create_zoneddatetime(ctx, &ts, s->timeZone, s->calendar);
}
}
}
JS_FreeValue(ctx, pt_val);
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "invalid epoch nanoseconds");
return js_create_zoneddatetime(ctx, &ts, s->timeZone, s->calendar);
}
ti_ns_to_timespec(total_ns, &ts);
}
}
- {
- js_int128_t epoch_ns = ti_timespec_to_ns(&ts);
- js_int128_t limit = (js_int128_t)8640000000000LL * 1000000000LL;
- if (epoch_ns < -limit || epoch_ns > limit)
- return JS_ThrowRangeError(ctx, "epoch nanoseconds outside valid limits");
- }
return js_create_zoneddatetime(ctx, &ts, s->timeZone, s->calendar);
}
ts.nsecs = (uint32_t)new_nsec;
}
}
- /* Validate epoch nanoseconds are within valid range */
- if (!is_valid_epoch_timespec(&ts))
- return JS_ThrowRangeError(ctx, "invalid ZonedDateTime string");
{
CalendarType cal = r.has_calendar ? r.calendar : CAL_ISO8601;
if (cal == CAL_UNKNOWN)