@@ -45088,7 +45088,7 @@ static JSValue json_parse_value(JSParseState *s)
45088
45088
default:
45089
45089
def_token:
45090
45090
if (s->token.val == TOK_EOF) {
45091
- js_parse_error(s, "unexpected end of input");
45091
+ js_parse_error(s, "Unexpected end of JSON input");
45092
45092
} else {
45093
45093
js_parse_error(s, "unexpected token: '%.*s'",
45094
45094
(int)(s->buf_ptr - s->token.ptr), s->token.ptr);
@@ -45255,22 +45255,27 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
45255
45255
JSValue v;
45256
45256
JSValueConst args[2];
45257
45257
45258
- if (JS_IsObject(val) ||
45259
- JS_IsBigInt(ctx, val) /* XXX: probably useless */
45258
+ /* check for object.toJSON method */
45259
+ /* ECMA specifies this is done only for Object and BigInt */
45260
+ /* we do it for BigFloat and BigDecimal as an extension */
45261
+ if (JS_IsObject(val) || JS_IsBigInt(ctx, val)
45262
+ #ifdef CONFIG_BIGNUM
45263
+ || JS_IsBigFloat(val) || JS_IsBigDecimal(val)
45264
+ #endif
45260
45265
) {
45261
- JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
45262
- if (JS_IsException(f))
45266
+ JSValue f = JS_GetProperty(ctx, val, JS_ATOM_toJSON);
45267
+ if (JS_IsException(f))
45268
+ goto exception;
45269
+ if (JS_IsFunction(ctx, f)) {
45270
+ v = JS_CallFree(ctx, f, val, 1, &key);
45271
+ JS_FreeValue(ctx, val);
45272
+ val = v;
45273
+ if (JS_IsException(val))
45263
45274
goto exception;
45264
- if (JS_IsFunction(ctx, f)) {
45265
- v = JS_CallFree(ctx, f, val, 1, &key);
45266
- JS_FreeValue(ctx, val);
45267
- val = v;
45268
- if (JS_IsException(val))
45269
- goto exception;
45270
- } else {
45271
- JS_FreeValue(ctx, f);
45272
- }
45275
+ } else {
45276
+ JS_FreeValue(ctx, f);
45273
45277
}
45278
+ }
45274
45279
45275
45280
if (!JS_IsUndefined(jsc->replacer_func)) {
45276
45281
args[0] = key;
@@ -45289,12 +45294,13 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
45289
45294
case JS_TAG_STRING:
45290
45295
case JS_TAG_INT:
45291
45296
case JS_TAG_FLOAT64:
45292
- #ifdef CONFIG_BIGNUM
45293
- case JS_TAG_BIG_FLOAT:
45294
- #endif
45295
45297
case JS_TAG_BOOL:
45296
45298
case JS_TAG_NULL:
45297
45299
case JS_TAG_BIG_INT:
45300
+ #ifdef CONFIG_BIGNUM
45301
+ case JS_TAG_BIG_FLOAT:
45302
+ case JS_TAG_BIG_DECIMAL:
45303
+ #endif
45298
45304
case JS_TAG_EXCEPTION:
45299
45305
return val;
45300
45306
default:
@@ -45324,36 +45330,29 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
45324
45330
tab = JS_UNDEFINED;
45325
45331
prop = JS_UNDEFINED;
45326
45332
45327
- switch (JS_VALUE_GET_NORM_TAG(val)) {
45328
- case JS_TAG_OBJECT:
45333
+ if (JS_IsObject(val)) {
45329
45334
p = JS_VALUE_GET_OBJ(val);
45330
45335
cl = p->class_id;
45331
45336
if (cl == JS_CLASS_STRING) {
45332
45337
val = JS_ToStringFree(ctx, val);
45333
45338
if (JS_IsException(val))
45334
45339
goto exception;
45335
- val = JS_ToQuotedStringFree(ctx, val);
45336
- if (JS_IsException(val))
45337
- goto exception;
45338
- return string_buffer_concat_value_free(jsc->b, val);
45340
+ goto concat_primitive;
45339
45341
} else if (cl == JS_CLASS_NUMBER) {
45340
45342
val = JS_ToNumberFree(ctx, val);
45341
45343
if (JS_IsException(val))
45342
45344
goto exception;
45343
- return string_buffer_concat_value_free(jsc->b, val);
45344
- } else if (cl == JS_CLASS_BOOLEAN) {
45345
- ret = string_buffer_concat_value(jsc->b, p->u.object_data);
45346
- JS_FreeValue(ctx, val);
45347
- return ret;
45348
- } else
45345
+ goto concat_primitive;
45346
+ } else if (cl == JS_CLASS_BOOLEAN || cl == JS_CLASS_BIG_INT
45349
45347
#ifdef CONFIG_BIGNUM
45350
- if (cl == JS_CLASS_BIG_FLOAT) {
45351
- return string_buffer_concat_value_free(jsc->b, val);
45352
- } else
45348
+ || cl == JS_CLASS_BIG_FLOAT
45349
+ || cl == JS_CLASS_BIG_DECIMAL
45353
45350
#endif
45354
- if (cl == JS_CLASS_BIG_INT) {
45355
- JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");
45356
- goto exception;
45351
+ )
45352
+ {
45353
+ /* This will thow the same error as for the primitive object */
45354
+ set_value(ctx, &val, JS_DupValue(ctx, p->u.object_data));
45355
+ goto concat_primitive;
45357
45356
}
45358
45357
v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
45359
45358
if (JS_IsException(v))
@@ -45466,6 +45465,9 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
45466
45465
JS_FreeValue(ctx, indent1);
45467
45466
JS_FreeValue(ctx, prop);
45468
45467
return 0;
45468
+ }
45469
+ concat_primitive:
45470
+ switch (JS_VALUE_GET_NORM_TAG(val)) {
45469
45471
case JS_TAG_STRING:
45470
45472
val = JS_ToQuotedStringFree(ctx, val);
45471
45473
if (JS_IsException(val))
@@ -45477,15 +45479,17 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
45477
45479
}
45478
45480
goto concat_value;
45479
45481
case JS_TAG_INT:
45480
- #ifdef CONFIG_BIGNUM
45481
- case JS_TAG_BIG_FLOAT:
45482
- #endif
45483
45482
case JS_TAG_BOOL:
45484
45483
case JS_TAG_NULL:
45485
45484
concat_value:
45486
45485
return string_buffer_concat_value_free(jsc->b, val);
45487
45486
case JS_TAG_BIG_INT:
45488
- JS_ThrowTypeError(ctx, "bigint are forbidden in JSON.stringify");
45487
+ #ifdef CONFIG_BIGNUM
45488
+ case JS_TAG_BIG_FLOAT:
45489
+ case JS_TAG_BIG_DECIMAL:
45490
+ #endif
45491
+ /* reject big numbers: use toJSON method to override */
45492
+ JS_ThrowTypeError(ctx, "Do not know how to serialize a BigInt");
45489
45493
goto exception;
45490
45494
default:
45491
45495
JS_FreeValue(ctx, val);
0 commit comments