@@ -968,6 +968,7 @@ struct JSObject {
968968 } u;
969969 /* byte sizes: 40/48/72 */
970970};
971+
971972enum {
972973 __JS_ATOM_NULL = JS_ATOM_NULL,
973974#define DEF(name, str) JS_ATOM_ ## name,
@@ -1103,6 +1104,12 @@ static void js_operator_set_finalizer(JSRuntime *rt, JSValue val);
11031104static void js_operator_set_mark(JSRuntime *rt, JSValueConst val,
11041105 JS_MarkFunc *mark_func);
11051106#endif
1107+
1108+ #define HINT_STRING 0
1109+ #define HINT_NUMBER 1
1110+ #define HINT_NONE 2
1111+ #define HINT_FORCE_ORDINARY (1 << 4) // don't try Symbol.toPrimitive
1112+ static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint);
11061113static JSValue JS_ToStringFree(JSContext *ctx, JSValue val);
11071114static int JS_ToBoolFree(JSContext *ctx, JSValue val);
11081115static int JS_ToInt32Free(JSContext *ctx, int32_t *pres, JSValue val);
@@ -9848,12 +9855,6 @@ void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id)
98489855 return p;
98499856}
98509857
9851- #define HINT_STRING 0
9852- #define HINT_NUMBER 1
9853- #define HINT_NONE 2
9854- /* don't try Symbol.toPrimitive */
9855- #define HINT_FORCE_ORDINARY (1 << 4)
9856-
98579858static JSValue JS_ToPrimitiveFree(JSContext *ctx, JSValue val, int hint)
98589859{
98599860 int i;
@@ -49404,6 +49405,7 @@ static const JSCFunctionListEntry js_global_funcs[] = {
4940449405 JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ),
4940549406 JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),
4940649407 JS_PROP_UNDEFINED_DEF("undefined", 0 ),
49408+ JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ),
4940749409};
4940849410
4940949411/* Date */
@@ -49484,7 +49486,7 @@ static char const month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
4948449486static char const day_names[] = "SunMonTueWedThuFriSat";
4948549487
4948649488static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
49487- double fields[9 ], int is_local, int force)
49489+ double fields[minimum_length(9) ], int is_local, int force)
4948849490{
4948949491 double dval;
4949049492 int64_t d, days, wd, y, i, md, h, m, s, ms, tz = 0;
@@ -49497,7 +49499,7 @@ static __exception int get_date_fields(JSContext *ctx, JSValueConst obj,
4949749499 return FALSE; /* NaN */
4949849500 d = 0; /* initialize all fields to 0 */
4949949501 } else {
49500- d = dval;
49502+ d = dval; /* assuming -8.64e15 <= dval <= -8.64e15 */
4950149503 if (is_local) {
4950249504 tz = -getTimezoneOffset(d);
4950349505 d += tz * 60000;
@@ -49545,7 +49547,7 @@ static double time_clip(double t) {
4954549547
4954649548/* The spec mandates the use of 'double' and it specifies the order
4954749549 of the operations */
49548- static double set_date_fields(double fields[], int is_local) {
49550+ static double set_date_fields(double fields[minimum_length(7) ], int is_local) {
4954949551 double y, m, dt, ym, mn, day, h, s, milli, time, tv;
4955049552 int yi, mi, i;
4955149553 int64_t days;
@@ -49649,9 +49651,9 @@ static JSValue set_date_field(JSContext *ctx, JSValueConst this_val,
4964949651 res = FALSE;
4965049652 fields[first_field + i] = trunc(a);
4965149653 }
49652- if (res && argc > 0) {
49654+ if (res && argc > 0)
4965349655 d = set_date_fields(fields, is_local);
49654- }
49656+
4965549657 return JS_SetThisTimeValue(ctx, this_val, d);
4965649658}
4965749659
@@ -49856,7 +49858,7 @@ static JSValue js_Date_UTC(JSContext *ctx, JSValueConst this_val,
4985649858 int argc, JSValueConst *argv)
4985749859{
4985849860 // UTC(y, mon, d, h, m, s, ms)
49859- double fields[9 ] = { 0, 0, 1, 0, 0 , 0, 0, 0, 0 };
49861+ double fields[] = { 0, 0, 1, 0, 0, 0, 0 };
4986049862 int i, n;
4986149863 double a;
4986249864
@@ -49936,14 +49938,15 @@ static BOOL string_get_digits(const uint8_t *sp, int *pp, int *pval,
4993649938static BOOL string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) {
4993749939 /* parse optional fractional part as milliseconds and truncate. */
4993849940 /* spec does not indicate which rounding should be used */
49939- int mul = 1000 , ms = 0, c, p_start, p = *pp;
49941+ int mul = 100 , ms = 0, c, p_start, p = *pp;
4994049942
4994149943 c = sp[p];
4994249944 if (c == '.' || c == ',') {
4994349945 p++;
4994449946 p_start = p;
4994549947 while ((c = sp[p]) >= '0' && c <= '9') {
49946- ms += (c - '0') * (mul /= 10);
49948+ ms += (c - '0') * mul;
49949+ mul /= 10;
4994749950 p++;
4994849951 if (p - p_start == 9)
4994949952 break;
@@ -49957,7 +49960,11 @@ static BOOL string_get_milliseconds(const uint8_t *sp, int *pp, int *pval) {
4995749960 return TRUE;
4995849961}
4995949962
49960- static BOOL string_get_timezone(const uint8_t *sp, int *pp, int *tzp, BOOL strict) {
49963+ static uint8_t upper_ascii(uint8_t c) {
49964+ return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
49965+ }
49966+
49967+ static BOOL string_get_tzoffset(const uint8_t *sp, int *pp, int *tzp, BOOL strict) {
4996149968 int tz = 0, sgn, hh, mm, p = *pp;
4996249969
4996349970 sgn = sp[p++];
@@ -49995,10 +50002,6 @@ static BOOL string_get_timezone(const uint8_t *sp, int *pp, int *tzp, BOOL stric
4999550002 return TRUE;
4999650003}
4999750004
49998- static uint8_t upper_ascii(uint8_t c) {
49999- return c >= 'a' && c <= 'z' ? c - 'a' + 'Z' : c;
50000- }
50001-
5000250005static BOOL string_match(const uint8_t *sp, int *pp, const char *s) {
5000350006 int p = *pp;
5000450007 while (*s != '\0') {
@@ -50091,15 +50094,51 @@ static BOOL js_date_parse_isostring(const uint8_t *sp, int fields[9], BOOL *is_l
5009150094 /* parse the time zone offset if present: [+-]HH:mm or [+-]HHmm */
5009250095 if (sp[p]) {
5009350096 *is_local = FALSE;
50094- if (!string_get_timezone (sp, &p, &fields[8], TRUE))
50097+ if (!string_get_tzoffset (sp, &p, &fields[8], TRUE))
5009550098 return FALSE;
5009650099 }
5009750100 /* error if extraneous characters */
5009850101 return sp[p] == '\0';
5009950102}
5010050103
50104+ static struct {
50105+ char name[6];
50106+ int16_t offset;
50107+ } const js_tzabbr[] = {
50108+ { "GMT", 0 }, // Greenwich Mean Time
50109+ { "UTC", 0 }, // Coordinated Universal Time
50110+ { "UT", 0 }, // Universal Time
50111+ { "Z", 0 }, // Zulu Time
50112+ { "EDT", -4 * 60 }, // Eastern Daylight Time
50113+ { "EST", -5 * 60 }, // Eastern Standard Time
50114+ { "CDT", -5 * 60 }, // Central Daylight Time
50115+ { "CST", -6 * 60 }, // Central Standard Time
50116+ { "MDT", -6 * 60 }, // Mountain Daylight Time
50117+ { "MST", -7 * 60 }, // Mountain Standard Time
50118+ { "PDT", -7 * 60 }, // Pacific Daylight Time
50119+ { "PST", -8 * 60 }, // Pacific Standard Time
50120+ { "WET", +0 * 60 }, // Western European Time
50121+ { "WEST", +1 * 60 }, // Western European Summer Time
50122+ { "CET", +1 * 60 }, // Central European Time
50123+ { "CEST", +2 * 60 }, // Central European Summer Time
50124+ { "EET", +2 * 60 }, // Eastern European Time
50125+ { "EEST", +3 * 60 }, // Eastern European Summer Time
50126+ };
50127+
50128+ static BOOL string_get_tzabbr(const uint8_t *sp, int *pp, int *offset) {
50129+ for (size_t i = 0; i < countof(js_tzabbr); i++) {
50130+ if (string_match(sp, pp, js_tzabbr[i].name)) {
50131+ *offset = js_tzabbr[i].offset;
50132+ return TRUE;
50133+ }
50134+ }
50135+ return FALSE;
50136+ }
50137+
5010150138/* parse toString, toUTCString and other formats */
50102- static BOOL js_date_parse_otherstring(const uint8_t *sp, int fields[9], BOOL *is_local) {
50139+ static BOOL js_date_parse_otherstring(const uint8_t *sp,
50140+ int fields[minimum_length(9)],
50141+ BOOL *is_local) {
5010350142 int c, i, val, p = 0, p_start;
5010450143 int num[3];
5010550144 BOOL has_year = FALSE;
@@ -50119,7 +50158,7 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp, int fields[9], BOOL *is
5011950158 while (string_skip_spaces(sp, &p)) {
5012050159 p_start = p;
5012150160 if ((c = sp[p]) == '+' || c == '-') {
50122- if (has_time && string_get_timezone (sp, &p, &fields[8], FALSE)) {
50161+ if (has_time && string_get_tzoffset (sp, &p, &fields[8], FALSE)) {
5012350162 *is_local = FALSE;
5012450163 } else {
5012550164 p++;
@@ -50165,11 +50204,6 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp, int fields[9], BOOL *is
5016550204 has_mon = TRUE;
5016650205 string_skip_until(sp, &p, "0123456789 -/(");
5016750206 } else
50168- if (c == 'Z') {
50169- *is_local = FALSE;
50170- p++;
50171- continue;
50172- } else
5017350207 if (has_time && string_match(sp, &p, "PM")) {
5017450208 if (fields[3] < 12)
5017550209 fields[3] += 12;
@@ -50180,34 +50214,7 @@ static BOOL js_date_parse_otherstring(const uint8_t *sp, int fields[9], BOOL *is
5018050214 fields[3] -= 12;
5018150215 continue;
5018250216 } else
50183- if (string_match(sp, &p, "GMT")
50184- || string_match(sp, &p, "UTC")
50185- || string_match(sp, &p, "UT")) {
50186- *is_local = FALSE;
50187- continue;
50188- } else
50189- if (string_match(sp, &p, "EDT")) {
50190- fields[8] = -4 * 60;
50191- *is_local = FALSE;
50192- continue;
50193- } else
50194- if (string_match(sp, &p, "EST") || string_match(sp, &p, "CDT")) {
50195- fields[8] = -5 * 60;
50196- *is_local = FALSE;
50197- continue;
50198- } else
50199- if (string_match(sp, &p, "CST") || string_match(sp, &p, "MDT")) {
50200- fields[8] = -6 * 60;
50201- *is_local = FALSE;
50202- continue;
50203- } else
50204- if (string_match(sp, &p, "MST") || string_match(sp, &p, "PDT")) {
50205- fields[8] = -7 * 60;
50206- *is_local = FALSE;
50207- continue;
50208- } else
50209- if (string_match(sp, &p, "PST")) {
50210- fields[8] = -8 * 60;
50217+ if (string_get_tzabbr(sp, &p, &fields[8])) {
5021150218 *is_local = FALSE;
5021250219 continue;
5021350220 } else
@@ -50350,9 +50357,7 @@ static JSValue js_date_Symbol_toPrimitive(JSContext *ctx, JSValueConst this_val,
5035050357 }
5035150358 switch (hint) {
5035250359 case JS_ATOM_number:
50353- #ifdef CONFIG_BIGNUM
5035450360 case JS_ATOM_integer:
50355- #endif
5035650361 hint_num = HINT_NUMBER;
5035750362 break;
5035850363 case JS_ATOM_string:
@@ -50376,6 +50381,7 @@ static JSValue js_date_getTimezoneOffset(JSContext *ctx, JSValueConst this_val,
5037650381 if (isnan(v))
5037750382 return JS_NAN;
5037850383 else
50384+ /* assuming -8.64e15 <= v <= -8.64e15 */
5037950385 return JS_NewInt64(ctx, getTimezoneOffset((int64_t)trunc(v)));
5038050386}
5038150387
@@ -50514,6 +50520,15 @@ static const JSCFunctionListEntry js_date_proto_funcs[] = {
5051450520 JS_CFUNC_DEF("toJSON", 1, js_date_toJSON ),
5051550521};
5051650522
50523+ JSValue JS_NewDate(JSContext *ctx, double epoch_ms)
50524+ {
50525+ JSValue obj = js_create_from_ctor(ctx, JS_UNDEFINED, JS_CLASS_DATE);
50526+ if (JS_IsException(obj))
50527+ return JS_EXCEPTION;
50528+ JS_SetObjectData(ctx, obj, __JS_NewFloat64(ctx, time_clip(epoch_ms)));
50529+ return obj;
50530+ }
50531+
5051750532void JS_AddIntrinsicDate(JSContext *ctx)
5051850533{
5051950534 JSValueConst obj;
@@ -52733,7 +52748,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
5273352748 /* XXX: create auto_initializer */
5273452749 {
5273552750 /* initialize Array.prototype[Symbol.unscopables] */
52736- char const unscopables[] =
52751+ static const char unscopables[] =
5273752752 "copyWithin" "\0"
5273852753 "entries" "\0"
5273952754 "fill" "\0"
0 commit comments