Jacek Caban : jscript: Don't expose named functions in expressions as a local variable in ES5 mode.

Alexandre Julliard julliard at winehq.org
Wed Apr 21 15:57:54 CDT 2021


Module: wine
Branch: master
Commit: e76450946660dc520d0274a10efed8c540f99e8e
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=e76450946660dc520d0274a10efed8c540f99e8e

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed Apr 21 17:23:17 2021 +0200

jscript: Don't expose named functions in expressions as a local variable in ES5 mode.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/jscript/compile.c            | 21 +++++++++++++++++----
 dlls/jscript/parser.h             |  1 +
 dlls/jscript/parser.y             |  1 +
 dlls/mshtml/tests/documentmode.js | 25 +++++++++++++++++++++++++
 4 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c
index 717ae00d053..9bb9ff13d14 100644
--- a/dlls/jscript/compile.c
+++ b/dlls/jscript/compile.c
@@ -1887,8 +1887,12 @@ static HRESULT visit_function_expression(compiler_ctx_t *ctx, function_expressio
     expr->func_id = ctx->func->func_cnt++;
     ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
 
-    return !expr->identifier || expr->event_target || alloc_variable(ctx, expr->identifier)
-        ? S_OK : E_OUTOFMEMORY;
+    if(!expr->identifier || expr->event_target)
+        return S_OK;
+    if(!expr->is_statement && ctx->parser->script->version >= SCRIPTLANGUAGEVERSION_ES5)
+        return S_OK;
+
+    return alloc_variable(ctx, expr->identifier) ? S_OK : E_OUTOFMEMORY;
 }
 
 static HRESULT visit_expression(compiler_ctx_t *ctx, expression_t *expr)
@@ -2069,7 +2073,15 @@ static HRESULT visit_statement(compiler_ctx_t *ctx, statement_t *stat)
     case STAT_CONTINUE:
     case STAT_EMPTY:
         break;
-    case STAT_EXPR:
+    case STAT_EXPR: {
+        expression_statement_t *expr_stat = (expression_statement_t*)stat;
+        if(expr_stat->expr) {
+            if(expr_stat->expr->type == EXPR_FUNC)
+                ((function_expression_t*)expr_stat->expr)->is_statement = TRUE;
+            hres = visit_expression(ctx, expr_stat->expr);
+        }
+        break;
+    }
     case STAT_RETURN:
     case STAT_THROW: {
         expression_statement_t *expr_stat = (expression_statement_t*)stat;
@@ -2410,7 +2422,8 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
             return hres;
 
         TRACE("[%d] func %s\n", i, debugstr_w(func->funcs[i].name));
-        if(func->funcs[i].name && !func->funcs[i].event_target) {
+        if((ctx->parser->script->version < SCRIPTLANGUAGEVERSION_ES5 || iter->is_statement) &&
+           func->funcs[i].name && !func->funcs[i].event_target) {
             local_ref_t *local_ref = lookup_local(func, func->funcs[i].name);
             func->funcs[i].local_ref = local_ref->ref;
             TRACE("found ref %s %d for %s\n", debugstr_w(local_ref->name), local_ref->ref, debugstr_w(func->funcs[i].name));
diff --git a/dlls/jscript/parser.h b/dlls/jscript/parser.h
index 3fa699c86d3..b88a52af242 100644
--- a/dlls/jscript/parser.h
+++ b/dlls/jscript/parser.h
@@ -302,6 +302,7 @@ typedef struct _function_expression_t {
     const WCHAR *src_str;
     DWORD src_len;
     unsigned func_id;
+    BOOL is_statement;
 
     struct _function_expression_t *next; /* for compiler */
 } function_expression_t;
diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y
index bfc83912ba1..f11119143b8 100644
--- a/dlls/jscript/parser.y
+++ b/dlls/jscript/parser.y
@@ -1386,6 +1386,7 @@ static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *ide
     ret->event_target = event_target;
     ret->src_str = src_str;
     ret->src_len = src_len;
+    ret->is_statement = FALSE;
     ret->next = NULL;
 
     return &ret->expr;
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index dfaaff44096..bd1255bc960 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -538,6 +538,7 @@ sync_test("delete_prop", function() {
 });
 
 var func_scope_val = 1;
+var func_scope_val2 = 2;
 
 sync_test("func_scope", function() {
     var func_scope_val = 2;
@@ -571,4 +572,28 @@ sync_test("func_scope", function() {
 
     window = 1;
     ok(window === window.self, "window = " + window);
+
+    ! function func_scope_val2() {};
+    ok(window.func_scope_val2 === 2, "window.func_scope_val2 = " + window.func_scope_val2);
+
+    var o = {};
+    (function(x) {
+        ok(x === o, "x = " + x);
+        ! function x() {};
+        ok(x === o, "x != o");
+    })(o);
+
+    (function(x) {
+        ok(x === o, "x = " + x);
+        1, function x() {};
+        ok(x === o, "x != o");
+    })(o);
+
+    (function() {
+        ! function x() {};
+        try {
+            x();
+            ok(false, "expected exception");
+        }catch(e) {}
+    })(o);
 });




More information about the wine-cvs mailing list