Module: wine Branch: master Commit: e76450946660dc520d0274a10efed8c540f99e8e URL: https://source.winehq.org/git/wine.git/?a=commit;h=e76450946660dc520d0274a10...
Author: Jacek Caban jacek@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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); });