From 30de39b2a7395295e8195683f264611062882d9a Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 20 Oct 2008 13:12:42 -0700 Subject: [PATCH] jscript: Treat function expressions with identifier as function declarations. --- dlls/jscript/dispex.c | 2 +- dlls/jscript/engine.c | 31 +++++++++++++-------------- dlls/jscript/engine.h | 24 ++++++++++----------- dlls/jscript/jscript.h | 1 + dlls/jscript/parser.y | 53 +++++++++++++--------------------------------- dlls/jscript/tests/lang.js | 39 ++++++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+), 68 deletions(-) diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 9717bfe26c0..31f47965ce2 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -941,7 +941,7 @@ HRESULT disp_propput(IDispatch *disp, DISPID id, LCID lcid, VARIANT *val, jsexce return hres; } -static HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, LCID lcid, VARIANT *var, +HRESULT jsdisp_propget_name(DispatchEx *obj, const WCHAR *name, LCID lcid, VARIANT *var, jsexcept_t *ei, IServiceProvider *caller) { DISPPARAMS dp = {NULL, NULL, 0, 0}; diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 815d5fd6667..bf82dfab66c 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -367,14 +367,14 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so DispatchEx *func_obj; VARIANT var; - hres = create_source_function(parser, func->parameter_list, func->source_elements, - ctx->scope_chain, func->src_str, func->src_len, &func_obj); + hres = create_source_function(parser, func->expr->parameter_list, func->expr->source_elements, + ctx->scope_chain, func->expr->src_str, func->expr->src_len, &func_obj); if(FAILED(hres)) return hres; V_VT(&var) = VT_DISPATCH; V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(func_obj); - hres = jsdisp_propput_name(ctx->var_disp, func->identifier, script->lcid, &var, ei, NULL); + hres = jsdisp_propput_name(ctx->var_disp, func->expr->identifier, script->lcid, &var, ei, NULL); jsdisp_release(func_obj); if(FAILED(hres)) return hres; @@ -1244,26 +1244,25 @@ static HRESULT assign_oper_eval(exec_ctx_t *ctx, expression_t *lexpr, expression HRESULT function_expression_eval(exec_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) { function_expression_t *expr = (function_expression_t*)_expr; - DispatchEx *dispex; VARIANT var; HRESULT hres; TRACE("\n"); - hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain, - expr->src_str, expr->src_len, &dispex); - if(FAILED(hres)) - return hres; - - V_VT(&var) = VT_DISPATCH; - V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex); - if(expr->identifier) { - hres = jsdisp_propput_name(ctx->var_disp, expr->identifier, ctx->parser->script->lcid, &var, ei, NULL/*FIXME*/); - if(FAILED(hres)) { - jsdisp_release(dispex); + hres = jsdisp_propget_name(ctx->var_disp, expr->identifier, ctx->parser->script->lcid, &var, ei, NULL/*FIXME*/); + if(FAILED(hres)) return hres; - } + }else { + DispatchEx *dispex; + + hres = create_source_function(ctx->parser, expr->parameter_list, expr->source_elements, ctx->scope_chain, + expr->src_str, expr->src_len, &dispex); + if(FAILED(hres)) + return hres; + + V_VT(&var) = VT_DISPATCH; + V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(dispex); } ret->type = EXPRVAL_VARIANT; diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 3746b5b6f2c..e02b717e744 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -17,12 +17,19 @@ */ typedef struct _source_elements_t source_elements_t; +typedef struct _function_expression_t function_expression_t; typedef struct _obj_literal_t { DispatchEx *obj; struct _obj_literal_t *next; } obj_literal_t; +typedef struct _function_declaration_t { + function_expression_t *expr; + + struct _function_declaration_t *next; +} function_declaration_t; + typedef struct _var_list_t { const WCHAR *identifier; @@ -30,6 +37,8 @@ typedef struct _var_list_t { } var_list_t; typedef struct _func_stack { + function_declaration_t *func_head; + function_declaration_t *func_tail; var_list_t *var_head; var_list_t *var_tail; @@ -288,32 +297,21 @@ struct _parameter_t { struct _parameter_t *next; }; -typedef struct _function_declaration_t { - const WCHAR *identifier; - parameter_t *parameter_list; - source_elements_t *source_elements; - const WCHAR *src_str; - DWORD src_len; - - struct _function_declaration_t *next; -} function_declaration_t; - struct _source_elements_t { statement_t *statement; statement_t *statement_tail; function_declaration_t *functions; - function_declaration_t *functions_tail; var_list_t *variables; }; -typedef struct { +struct _function_expression_t { expression_t expr; const WCHAR *identifier; parameter_t *parameter_list; source_elements_t *source_elements; const WCHAR *src_str; DWORD src_len; -} function_expression_t; +}; typedef struct { expression_t expr; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 59e23535374..b416f6ed1c8 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -128,6 +128,7 @@ HRESULT disp_propput(IDispatch*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvide HRESULT jsdisp_propget(DispatchEx*,DISPID,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT jsdisp_propput_name(DispatchEx*,const WCHAR*,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT jsdisp_propput_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); +HRESULT jsdisp_propget_name(DispatchEx*,LPCWSTR,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT jsdisp_propget_idx(DispatchEx*,DWORD,LCID,VARIANT*,jsexcept_t*,IServiceProvider*); HRESULT jsdisp_get_id(DispatchEx*,const WCHAR*,DWORD,DISPID*); diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index af3d35de5e0..7a74e467e06 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -142,11 +142,8 @@ static expression_t *new_literal_expression(parser_ctx_t*,literal_t*); static expression_t *new_array_literal_expression(parser_ctx_t*,element_list_t*,int); static expression_t *new_prop_and_value_expression(parser_ctx_t*,property_list_t*); -static function_declaration_t *new_function_declaration(parser_ctx_t*,const WCHAR*,parameter_list_t*, - source_elements_t*,const WCHAR*,DWORD); static source_elements_t *new_source_elements(parser_ctx_t*); static source_elements_t *source_elements_add_statement(source_elements_t*,statement_t*); -static source_elements_t *source_elements_add_function(source_elements_t*,function_declaration_t*); %} @@ -165,7 +162,6 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi struct _element_list_t *element_list; expression_t *expr; const WCHAR *identifier; - function_declaration_t *function_declaration; struct _parameter_list_t *parameter_list; struct _property_list_t *property_list; source_elements_t *source_elements; @@ -207,7 +203,6 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi %type TryStatement %type Finally %type StatementList StatementList_opt -%type FunctionDeclaration %type FormalParameterList FormalParameterList_opt %type Expression Expression_opt %type ExpressionNoIn ExpressionNoIn_opt @@ -267,13 +262,6 @@ SourceElements : /* empty */ { $$ = new_source_elements(ctx); } | SourceElements Statement { $$ = source_elements_add_statement($1, $2); } - | SourceElements FunctionDeclaration - { $$ = source_elements_add_function($1, $2); } - -/* ECMA-262 3rd Edition 13 */ -FunctionDeclaration - : KFunction tIdentifier '(' FormalParameterList_opt ')' '{' FunctionBody '}' - { $$ = new_function_declaration(ctx, $2, $4, $7, $1, $8-$1+1); } /* ECMA-262 3rd Edition 13 */ FunctionExpression @@ -1287,6 +1275,18 @@ static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *ide ret->src_str = src_str; ret->src_len = src_len; + if(ret->identifier) { + function_declaration_t *decl = parser_alloc(ctx, sizeof(function_declaration_t)); + + decl->expr = ret; + decl->next = NULL; + + if(ctx->func_stack->func_tail) + ctx->func_stack->func_tail = ctx->func_stack->func_tail->next = decl; + else + ctx->func_stack->func_head = ctx->func_stack->func_tail = decl; + } + return &ret->expr; } @@ -1474,21 +1474,6 @@ static expression_t *new_literal_expression(parser_ctx_t *ctx, literal_t *litera return &ret->expr; } -static function_declaration_t *new_function_declaration(parser_ctx_t *ctx, const WCHAR *identifier, - parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len) -{ - function_declaration_t *ret = parser_alloc(ctx, sizeof(function_declaration_t)); - - ret->identifier = identifier; - ret->parameter_list = parameter_list ? parameter_list->head : NULL; - ret->source_elements = source_elements; - ret->src_str = src_str; - ret->src_len = src_len; - ret->next = NULL; - - return ret; -} - static source_elements_t *new_source_elements(parser_ctx_t *ctx) { source_elements_t *ret = parser_alloc(ctx, sizeof(source_elements_t)); @@ -1508,17 +1493,6 @@ static source_elements_t *source_elements_add_statement(source_elements_t *sourc return source_elements; } -static source_elements_t *source_elements_add_function(source_elements_t *source_elements, - function_declaration_t *function_declaration) -{ - if(source_elements->functions_tail) - source_elements->functions_tail = source_elements->functions_tail->next = function_declaration; - else - source_elements->functions = source_elements->functions_tail = function_declaration; - - return source_elements; -} - statement_list_t *new_statement_list(parser_ctx_t *ctx, statement_t *statement) { statement_list_t *ret = parser_alloc_tmp(ctx, sizeof(statement_list_t)); @@ -1539,6 +1513,7 @@ static void push_func(parser_ctx_t *ctx) { func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t)); + new_func->func_head = new_func->func_tail = NULL; new_func->var_head = new_func->var_tail = NULL; new_func->next = ctx->func_stack; @@ -1547,6 +1522,7 @@ static void push_func(parser_ctx_t *ctx) static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source) { + source->functions = ctx->func_stack->func_head; source->variables = ctx->func_stack->var_head; pop_func(ctx); @@ -1555,6 +1531,7 @@ static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_element static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) { + source->functions = ctx->func_stack->func_head; source->variables = ctx->func_stack->var_head; pop_func(ctx); diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 71dd2aae3d3..0d68f377724 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -832,4 +832,43 @@ ok((Infinity != NaN) === true, "(Infinity != NaN) !== true"); ok((Infinity != NaN) === true, "(Infinity != NaN) !== true"); ok((0 == NaN) === false, "(0 === NaN) != false"); + +ok(typeof(testFunc2) === "function", "typeof(testFunc2) = " + typeof(testFunc2)); +tmp = testFunc2(1); +ok(tmp === 2, "testFunc2(1) = " + tmp); +function testFunc2(x) { return x+1; } + +ok(typeof(testFunc3) === "function", "typeof(testFunc3) = " + typeof(testFunc3)); +tmp = testFunc3(1); +ok(tmp === 3, "testFunc3(1) = " + tmp); +tmp = function testFunc3(x) { return x+2; }; + +tmp = testFunc4(1); +ok(tmp === 5, "testFunc4(1) = " + tmp); +tmp = function testFunc4(x) { return x+3; }; +tmp = testFunc4(1); +testFunc4 = 1; +ok(testFunc4 === 1, "testFunc4 = " + testFunc4); +ok(tmp === 5, "testFunc4(1) = " + tmp); +tmp = function testFunc4(x) { return x+4; }; +ok(testFunc4 === 1, "testFunc4 = " + testFunc4); + +function testEmbededFunctions() { + ok(typeof(testFunc5) === "function", "typeof(testFunc5) = " + typeof(testFunc5)); + tmp = testFunc5(1); + ok(tmp === 3, "testFunc5(1) = " + tmp); + tmp = function testFunc5(x) { return x+2; }; + + tmp = testFunc6(1); + ok(tmp === 5, "testFunc6(1) = " + tmp); + tmp = function testFunc6(x) { return x+3; }; + tmp = testFunc6(1); + ok(tmp === 5, "testFunc6(1) = " + tmp); + tmp = function testFunc6(x) { return x+4; }; + testFunc6 = 1; + ok(testFunc6 === 1, "testFunc4 = " + testFunc6); +} + +testEmbededFunctions(); + reportSuccess(); -- 2.11.4.GIT