From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/function.c | 46 ++++++++++++++++++++++++++++++- dlls/jscript/tests/lang.js | 3 ++ dlls/mshtml/tests/documentmode.js | 15 ++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/dlls/jscript/function.c b/dlls/jscript/function.c index 40ff015121b..ceaf50e8538 100644 --- a/dlls/jscript/function.c +++ b/dlls/jscript/function.c @@ -195,7 +195,51 @@ static HRESULT Arguments_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op return S_OK; }
+static HRESULT Arguments_get_caller(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) +{ + ArgumentsInstance *arguments = arguments_from_jsdisp(jsthis); + call_frame_t *frame; + HRESULT hres; + + TRACE("\n"); + + for(frame = ctx->call_ctx; frame; frame = frame->prev_frame) { + if(frame->arguments_obj == &arguments->jsdisp) { + frame = frame->prev_frame; + if(!frame || !frame->function_instance) + break; + if(!frame->arguments_obj) { + hres = setup_arguments_object(ctx, frame); + if(FAILED(hres)) + return hres; + } + *r = jsval_obj(jsdisp_addref(frame->arguments_obj)); + return S_OK; + } + } + + *r = jsval_null(); + return S_OK; +} + +static const builtin_prop_t Arguments_props[] = { + {L"caller", NULL, 0, Arguments_get_caller}, +}; + static const builtin_info_t Arguments_info = { + .class = JSCLASS_ARGUMENTS, + .call = Arguments_value, + .props_cnt = ARRAY_SIZE(Arguments_props), + .props = Arguments_props, + .destructor = Arguments_destructor, + .lookup_prop = Arguments_lookup_prop, + .next_prop = Arguments_next_prop, + .prop_get = Arguments_prop_get, + .prop_put = Arguments_prop_put, + .gc_traverse = Arguments_gc_traverse +}; + +static const builtin_info_t Arguments_ES5_info = { .class = JSCLASS_ARGUMENTS, .call = Arguments_value, .destructor = Arguments_destructor, @@ -215,7 +259,7 @@ HRESULT setup_arguments_object(script_ctx_t *ctx, call_frame_t *frame) if(!args) return E_OUTOFMEMORY;
- hres = init_dispex_from_constr(&args->jsdisp, ctx, &Arguments_info, ctx->object_constr); + hres = init_dispex_from_constr(&args->jsdisp, ctx, ctx->version < SCRIPTLANGUAGEVERSION_ES5 ? &Arguments_info : &Arguments_ES5_info, ctx->object_constr); if(FAILED(hres)) { free(args); return hres; diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 2ddfc3a8341..89f52298fb3 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -447,6 +447,9 @@ obj1.func = function () { ok(arguments.length === 1, "arguments.length is not 1"); ok(arguments["0"] === true, "arguments[0] is not true"); ok(typeof(arguments.callee) === "function", "typeof(arguments.calee) = " + typeof(arguments.calee)); + ok(arguments.caller === null, "arguments.caller = " + arguments.caller); + function test_caller() { ok(arguments.caller === foobar.arguments, "nested arguments.caller = " + arguments.caller); } + function foobar() { test_caller(); } foobar();
return "test"; }; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 95c033f46dd..c2f0a7ecb82 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -892,18 +892,33 @@ sync_test("for..in", function() { });
sync_test("function caller", function() { + var v = document.documentMode; + ok(Function.prototype.hasOwnProperty("caller"), "caller not prop of Function.prototype"); + if(v < 9) + ok(arguments.hasOwnProperty("caller"), "caller not prop of arguments"); + else + ok(!("caller" in arguments), "caller in arguments");
function test_caller(expected_caller, stop) { ok(test_caller.caller === expected_caller, "caller = " + test_caller.caller); + if(v < 9) + ok(arguments.caller === expected_caller.arguments, "arguments.caller = " + arguments.caller); + if(stop) return; function nested() { ok(nested.caller === test_caller, "nested caller = " + nested.caller); + if(v < 9) + ok(arguments.caller === test_caller.arguments, "nested arguments.caller = " + arguments.caller); test_caller(nested, true); ok(test_caller.caller === expected_caller, "caller within nested = " + test_caller.caller); + if(v < 9) + ok(test_caller.arguments.caller === expected_caller.arguments, "arguments.caller within nested = " + test_caller.arguments.caller); } nested(); ok(test_caller.caller === expected_caller, "caller after nested = " + test_caller.caller); + if(v < 9) + ok(arguments.caller === expected_caller.arguments, "arguments.caller after nested = " + arguments.caller); } ok(test_caller.hasOwnProperty("caller"), "caller not prop of test_caller"); ok(test_caller.caller === null, "test_caller.caller = " + test_caller.caller);