@@ -45088,7 +45088,7 @@ static JSValue json_parse_value(JSParseState *s)
4508845088 default:
4508945089 def_token:
4509045090 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");
4509245092 } else {
4509345093 js_parse_error(s, "unexpected token: '%.*s'",
4509445094 (int)(s->buf_ptr - s->token.ptr), s->token.ptr);
@@ -45255,22 +45255,27 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
4525545255 JSValue v;
4525645256 JSValueConst args[2];
4525745257
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
4526045265 ) {
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))
4526345274 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);
4527345277 }
45278+ }
4527445279
4527545280 if (!JS_IsUndefined(jsc->replacer_func)) {
4527645281 args[0] = key;
@@ -45289,12 +45294,13 @@ static JSValue js_json_check(JSContext *ctx, JSONStringifyContext *jsc,
4528945294 case JS_TAG_STRING:
4529045295 case JS_TAG_INT:
4529145296 case JS_TAG_FLOAT64:
45292- #ifdef CONFIG_BIGNUM
45293- case JS_TAG_BIG_FLOAT:
45294- #endif
4529545297 case JS_TAG_BOOL:
4529645298 case JS_TAG_NULL:
4529745299 case JS_TAG_BIG_INT:
45300+ #ifdef CONFIG_BIGNUM
45301+ case JS_TAG_BIG_FLOAT:
45302+ case JS_TAG_BIG_DECIMAL:
45303+ #endif
4529845304 case JS_TAG_EXCEPTION:
4529945305 return val;
4530045306 default:
@@ -45324,36 +45330,29 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
4532445330 tab = JS_UNDEFINED;
4532545331 prop = JS_UNDEFINED;
4532645332
45327- switch (JS_VALUE_GET_NORM_TAG(val)) {
45328- case JS_TAG_OBJECT:
45333+ if (JS_IsObject(val)) {
4532945334 p = JS_VALUE_GET_OBJ(val);
4533045335 cl = p->class_id;
4533145336 if (cl == JS_CLASS_STRING) {
4533245337 val = JS_ToStringFree(ctx, val);
4533345338 if (JS_IsException(val))
4533445339 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;
4533945341 } else if (cl == JS_CLASS_NUMBER) {
4534045342 val = JS_ToNumberFree(ctx, val);
4534145343 if (JS_IsException(val))
4534245344 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
4534945347#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
4535345350#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;
4535745356 }
4535845357 v = js_array_includes(ctx, jsc->stack, 1, (JSValueConst *)&val);
4535945358 if (JS_IsException(v))
@@ -45466,6 +45465,9 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
4546645465 JS_FreeValue(ctx, indent1);
4546745466 JS_FreeValue(ctx, prop);
4546845467 return 0;
45468+ }
45469+ concat_primitive:
45470+ switch (JS_VALUE_GET_NORM_TAG(val)) {
4546945471 case JS_TAG_STRING:
4547045472 val = JS_ToQuotedStringFree(ctx, val);
4547145473 if (JS_IsException(val))
@@ -45477,15 +45479,17 @@ static int js_json_to_str(JSContext *ctx, JSONStringifyContext *jsc,
4547745479 }
4547845480 goto concat_value;
4547945481 case JS_TAG_INT:
45480- #ifdef CONFIG_BIGNUM
45481- case JS_TAG_BIG_FLOAT:
45482- #endif
4548345482 case JS_TAG_BOOL:
4548445483 case JS_TAG_NULL:
4548545484 concat_value:
4548645485 return string_buffer_concat_value_free(jsc->b, val);
4548745486 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");
4548945493 goto exception;
4549045494 default:
4549145495 JS_FreeValue(ctx, val);
0 commit comments