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