jscript: Defer lookup to the actual locals for function statements.
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> Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
603d7f406c
commit
2bdce91e8f
|
@ -587,7 +587,8 @@ static HRESULT detach_scope(script_ctx_t *ctx, call_frame_t *frame, scope_chain_
|
||||||
scope->obj = to_disp(scope->jsobj);
|
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)));
|
jsdisp_propput_name(scope->jsobj, func->name, jsval_obj(jsdisp_addref(frame->function_instance)));
|
||||||
|
|
||||||
index = scope->scope_index;
|
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 */
|
/* 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");
|
TRACE("returning a function from scope chain\n");
|
||||||
ret->type = EXPRVAL_JSVAL;
|
ret->type = EXPRVAL_JSVAL;
|
||||||
ret->u.val = jsval_obj(jsdisp_addref(scope->frame->function_instance));
|
ret->u.val = jsval_obj(jsdisp_addref(scope->frame->function_instance));
|
||||||
|
|
|
@ -1691,6 +1691,34 @@ sync_test("functions scope", function() {
|
||||||
func_outer(o);
|
func_outer(o);
|
||||||
func();
|
func();
|
||||||
ok(ret === o, "ret != o");
|
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() {
|
sync_test("console", function() {
|
||||||
|
|
Loading…
Reference in New Issue