Module: wine Branch: master Commit: 34a9c343805f0cd526e1b1665d4f59005b421523 URL: https://source.winehq.org/git/wine.git/?a=commit;h=34a9c343805f0cd526e1b1665...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Apr 20 19:12:25 2021 +0200
jscript: Support replacer argument in JSON.stringify.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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],