[PATCH v2 1/7] jscript: Defer lookup to the actual locals for function statements.

Gabriel Ivăncescu gabrielopcode at gmail.com
Wed Apr 13 09:34:52 CDT 2022


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 at 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() {
-- 
2.34.1




More information about the wine-devel mailing list