Module: wine Branch: master Commit: 50a84b454541eba099b082d9fa912df538b1c4ab URL: http://source.winehq.org/git/wine.git/?a=commit;h=50a84b454541eba099b082d9fa...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Sep 30 17:47:40 2008 +0200
jscript: Allocate variables when entering execution context.
---
dlls/jscript/engine.c | 11 +++++++++- dlls/jscript/engine.h | 15 +++++++++++++ dlls/jscript/parser.y | 49 +++++++++++++++++++++++++++++++++++++++++-- dlls/jscript/tests/lang.js | 18 ++++++++++++++++ 4 files changed, 89 insertions(+), 4 deletions(-)
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 5d231f2..2c96bc4 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -351,6 +351,7 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so script_ctx_t *script = parser->script; function_declaration_t *func; parser_ctx_t *prev_parser; + var_list_t *var; VARIANT val, tmp; statement_t *stat; exec_ctx_t *prev_ctx; @@ -369,7 +370,15 @@ HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *so 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); - IDispatchEx_Release(_IDispatchEx_(func_obj)); + jsdisp_release(func_obj); + if(FAILED(hres)) + return hres; + } + + for(var = source->variables; var; var = var->next) { + DISPID id = 0; + + hres = jsdisp_get_id(ctx->var_disp, var->identifier, fdexNameEnsure, &id); if(FAILED(hres)) return hres; } diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index beabc9b..3746b5b 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -23,6 +23,19 @@ typedef struct _obj_literal_t { struct _obj_literal_t *next; } obj_literal_t;
+typedef struct _var_list_t { + const WCHAR *identifier; + + struct _var_list_t *next; +} var_list_t; + +typedef struct _func_stack { + var_list_t *var_head; + var_list_t *var_tail; + + struct _func_stack *next; +} func_stack_t; + typedef struct _parser_ctx_t { LONG ref;
@@ -38,6 +51,7 @@ typedef struct _parser_ctx_t { jsheap_t heap;
obj_literal_t *obj_literals; + func_stack_t *func_stack;
struct _parser_ctx_t *next; } parser_ctx_t; @@ -289,6 +303,7 @@ struct _source_elements_t { statement_t *statement_tail; function_declaration_t *functions; function_declaration_t *functions_tail; + var_list_t *variables; };
typedef struct { diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 96ca9e5..98ee250 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -31,6 +31,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); static int parser_error(const char*); static BOOL allow_auto_semicolon(parser_ctx_t*); static void program_parsed(parser_ctx_t*,source_elements_t*); +static source_elements_t *function_body_parsed(parser_ctx_t*,source_elements_t*);
typedef struct _statement_list_t { statement_t *head; @@ -120,6 +121,12 @@ typedef struct _parameter_list_t { static parameter_list_t *new_parameter_list(parser_ctx_t*,const WCHAR*); static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,const WCHAR*);
+static void push_func(parser_ctx_t*); +static inline void pop_func(parser_ctx_t *ctx) +{ + ctx->func_stack = ctx->func_stack->next; +} + static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*, source_elements_t*,const WCHAR*,DWORD); static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*); @@ -244,6 +251,7 @@ static source_elements_t *source_elements_add_function(source_elements_t*,functi %type <property_list> PropertyNameAndValueList %type <literal> PropertyName %type <literal> BooleanLiteral +%type <srcptr> KFunction
%%
@@ -261,17 +269,20 @@ SourceElements
/* ECMA-262 3rd Edition 13 */ FunctionDeclaration - : kFUNCTION tIdentifier '(' FormalParameterList_opt ')' '{' FunctionBody '}' + : KFunction tIdentifier '(' FormalParameterList_opt ')' '{' FunctionBody '}' { $$ = new_function_declaration(ctx, $2, $4, $7, $1, $8-$1+1); }
/* ECMA-262 3rd Edition 13 */ FunctionExpression - : kFUNCTION Identifier_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}' + : KFunction Identifier_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}' { $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); }
+KFunction + : kFUNCTION { push_func(ctx); $$ = $1; } + /* ECMA-262 3rd Edition 13 */ FunctionBody - : SourceElements { $$ = $1; } + : SourceElements { $$ = function_body_parsed(ctx, $1); }
/* ECMA-262 3rd Edition 13 */ FormalParameterList @@ -1018,11 +1029,20 @@ static statement_t *new_block_statement(parser_ctx_t *ctx, statement_list_t *lis static variable_declaration_t *new_variable_declaration(parser_ctx_t *ctx, const WCHAR *identifier, expression_t *expr) { variable_declaration_t *ret = parser_alloc(ctx, sizeof(variable_declaration_t)); + var_list_t *var_list = parser_alloc(ctx, sizeof(var_list_t));
ret->identifier = identifier; ret->expr = expr; ret->next = NULL;
+ var_list->identifier = identifier; + var_list->next = NULL; + + if(ctx->func_stack->var_tail) + ctx->func_stack->var_tail = ctx->func_stack->var_tail->next = var_list; + else + ctx->func_stack->var_head = ctx->func_stack->var_tail = var_list; + return ret; }
@@ -1511,8 +1531,29 @@ statement_list_t *statement_list_add(statement_list_t *list, statement_t *statem return list; }
+static void push_func(parser_ctx_t *ctx) +{ + func_stack_t *new_func = parser_alloc_tmp(ctx, sizeof(func_stack_t)); + + new_func->var_head = new_func->var_tail = NULL; + + new_func->next = ctx->func_stack; + ctx->func_stack = new_func; +} + +static source_elements_t *function_body_parsed(parser_ctx_t *ctx, source_elements_t *source) +{ + source->variables = ctx->func_stack->var_head; + pop_func(ctx); + + return source; +} + static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) { + source->variables = ctx->func_stack->var_head; + pop_func(ctx); + ctx->source = source; ctx->hres = S_OK; } @@ -1553,6 +1594,8 @@ HRESULT script_parse(script_ctx_t *ctx, const WCHAR *code, parser_ctx_t **ret) mark = jsheap_mark(&ctx->tmp_heap); jsheap_init(&parser_ctx->heap);
+ push_func(parser_ctx); + parser_parse(parser_ctx); jsheap_clear(mark); if(FAILED(parser_ctx->hres)) { diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 9bbdafe..de45d59 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -721,4 +721,22 @@ tmp.testWith = true; with(tmp) ok(testWith === true, "testWith !== true");
+if(false) { + var varTest1 = true; +} + +ok(varTest1 === undefined, "varTest1 = " + varTest1); +ok(varTest2 === undefined, "varTest2 = " + varTest1); + +var varTest2; + +function varTestFunc(varTest3) { + var varTest3; + + ok(varTest3 === 3, "varTest3 = " + varTest3); + ok(varTest4 === undefined, "varTest4 = " + varTest4); + + var varTest4; +} + reportSuccess();