Functions declared as function statements have an associated local_ref and can be changed from within themselves by using their name (by literally changing the local variable), while function expressions can not.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/engine.c | 6 ++++-- dlls/mshtml/tests/es5.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index c483f2a..73b9d86 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -587,7 +587,8 @@ static HRESULT detach_scope(script_ctx_t *ctx, call_frame_t *frame, scope_chain_ scope->obj = to_disp(scope->jsobj); }
- if (scope == frame->base_scope && func->name && ctx->version >= SCRIPTLANGUAGEVERSION_ES5) + if (scope == frame->base_scope && func->name && func->local_ref == INVALID_LOCAL_REF && + ctx->version >= SCRIPTLANGUAGEVERSION_ES5) jsdisp_propput_name(scope->jsobj, func->name, jsval_obj(jsdisp_addref(frame->function_instance)));
index = scope->scope_index; @@ -716,7 +717,8 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re }
/* ECMA-262 5.1 Edition 13 */ - if(func->name && ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && !wcscmp(identifier, func->name)) { + if(func->name && ctx->version >= SCRIPTLANGUAGEVERSION_ES5 && + func->local_ref == INVALID_LOCAL_REF && !wcscmp(identifier, func->name)) { TRACE("returning a function from scope chain\n"); ret->type = EXPRVAL_JSVAL; ret->u.val = jsval_obj(jsdisp_addref(scope->frame->function_instance)); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index e8ee713..43a6ce7 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -1691,6 +1691,34 @@ sync_test("functions scope", function() { func_outer(o); func(); ok(ret === o, "ret != o"); + + func_outer = function g() { + var g2 = g; + g = 10; + ok(g !== 10, "g was redefined to 10"); + g = function() {}; + ok(g === g2, "g !== g2: " + g); + } + func_outer(); + + function h() { + h = 1; + ok(h === 1, "h was not redefined: " + h); + } + h(); + ok(h === 1, "h = " + h); + + function h2() { return function() { h2 = 2; }; } + h2()(); + ok(h2 === 2, "h2 = " + h2); + + (function e() { + var f = e; + ok(typeof(f) === "function", "f = " + f); + (function () { e = 1; })(); + e = 2; + ok(f === e, "f != e"); + })(); });
sync_test("console", function() {