Jacek Caban : jscript: Support replacer argument in JSON.stringify.
Alexandre Julliard
julliard at winehq.org
Tue Apr 20 16:27:47 CDT 2021
Module: wine
Branch: master
Commit: 34a9c343805f0cd526e1b1665d4f59005b421523
URL: https://source.winehq.org/git/wine.git/?a=commit;h=34a9c343805f0cd526e1b1665d4f59005b421523
Author: Jacek Caban <jacek at codeweavers.com>
Date: Tue Apr 20 19:12:25 2021 +0200
jscript: Support replacer argument in JSON.stringify.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/jscript/json.c | 38 +++++++++++++++++++++++++++++++-------
dlls/jscript/tests/api.js | 21 ++++++++++++++++++++-
2 files changed, 51 insertions(+), 8 deletions(-)
diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c
index f3b523d63d8..a8014f95b4f 100644
--- a/dlls/jscript/json.c
+++ b/dlls/jscript/json.c
@@ -320,6 +320,8 @@ typedef struct {
size_t stack_size;
WCHAR gap[11]; /* according to the spec, it's no longer than 10 chars */
+
+ jsdisp_t *replacer;
} stringify_ctx_t;
static BOOL stringify_push_obj(stringify_ctx_t *ctx, jsdisp_t *obj)
@@ -656,7 +658,22 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *na
FIXME("Use toJSON.\n");
}
- /* FIXME: Support replacer replacer. */
+ if(ctx->replacer) {
+ jsstr_t *name_str;
+ jsval_t args[2];
+ if(!(name_str = jsstr_alloc(name))) {
+ jsval_release(value);
+ return E_OUTOFMEMORY;
+ }
+ args[0] = jsval_string(name_str);
+ args[1] = value;
+ hres = jsdisp_call_value(ctx->replacer, to_disp(object), DISPATCH_METHOD, ARRAY_SIZE(args), args, &v);
+ jsstr_release(name_str);
+ jsval_release(value);
+ if(FAILED(hres))
+ return hres;
+ value = v;
+ }
v = value;
hres = maybe_to_primitive(ctx->ctx, v, &value);
@@ -736,8 +753,8 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsdisp_t *object, const WCHAR *na
/* ECMA-262 5.1 Edition 15.12.3 */
static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{
- stringify_ctx_t stringify_ctx = {ctx, NULL,0,0, NULL,0,0, {0}};
- jsdisp_t *obj;
+ stringify_ctx_t stringify_ctx = { ctx };
+ jsdisp_t *obj = NULL, *replacer;
HRESULT hres;
TRACE("\n");
@@ -748,9 +765,14 @@ static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
return S_OK;
}
- if(argc >= 2 && is_object_instance(argv[1])) {
- FIXME("Replacer %s not yet supported\n", debugstr_jsval(argv[1]));
- return E_NOTIMPL;
+ if(argc >= 2 && is_object_instance(argv[1]) && get_object(argv[1]) &&
+ (replacer = to_jsdisp(get_object(argv[1])))) {
+ if(is_callable(replacer)) {
+ stringify_ctx.replacer = jsdisp_addref(replacer);
+ }else if(is_class(replacer, JSCLASS_ARRAY)) {
+ FIXME("Array replacer not yet supported\n");
+ return E_NOTIMPL;
+ }
}
if(argc >= 3) {
@@ -758,7 +780,7 @@ static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
hres = maybe_to_primitive(ctx, argv[2], &space_val);
if(FAILED(hres))
- return hres;
+ goto fail;
if(is_number(space_val)) {
double n = get_number(space_val);
@@ -805,6 +827,8 @@ static HRESULT JSON_stringify(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
fail:
if(obj)
jsdisp_release(obj);
+ if(stringify_ctx.replacer)
+ jsdisp_release(stringify_ctx.replacer);
heap_free(stringify_ctx.buf);
heap_free(stringify_ctx.stack);
return hres;
diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js
index 564dfc16f30..d5d8e7d34b9 100644
--- a/dlls/jscript/tests/api.js
+++ b/dlls/jscript/tests/api.js
@@ -1923,7 +1923,7 @@ ok(isNaN(tmp), "Math.tan(-Infinity) is not NaN");
[[NaN], "null"],
[[Infinity], "null"],
[[-Infinity], "null"],
- [[{prop1: true, prop2: "string"}], "{\"prop1\":true,\"prop2\":\"string\"}"],
+ [[{prop1: true, prop2: "string", func1: function() {}}], "{\"prop1\":true,\"prop2\":\"string\"}"],
[[{prop1: true, prop2: testObj, prop3: undefined}], "{\"prop1\":true}"],
[[{prop1: true, prop2: {prop: "string"}},undefined," "],
"{\n \"prop1\": true,\n \"prop2\": {\n \"prop\": \"string\"\n }\n}"],
@@ -1951,6 +1951,25 @@ ok(isNaN(tmp), "Math.tan(-Infinity) is not NaN");
ok(s === undefined || s === "undefined" /* broken on some old versions */,
"stringify(undefined) returned " + s + " expected undefined");
+ s = JSON.stringify(1, function(name, value) {
+ ok(name === "", "name = " + name);
+ ok(value === 1, "value = " + value);
+ ok(this[name] === value, "this[" + name + "] = " + this[name] + " expected " + value);
+ return 2;
+ });
+ ok(s == "2", "s = " + s);
+
+ var o = { prop: 1 };
+ s = JSON.stringify(1, function(name, value) {
+ ok(name === "" || name === "prop", "name = " + name);
+ ok(value === 1 || value === true, "value = " + value);
+ ok(this[name] === value, "this[" + name + "] = " + this[name] + " expected " + value);
+ if(name === "") return o;
+ ok(this === o, "this != o");
+ return value;
+ });
+ ok(s == "{\"prop\":1}", "s = " + s);
+
var parse_tests = [
["true", true],
[" \nnull ", null],
More information about the wine-cvs
mailing list