Module: wine Branch: master Commit: 170bb3771f43f1120435e98ea38543d5a667f9bc URL: http://source.winehq.org/git/wine.git/?a=commit;h=170bb3771f43f1120435e98ea3...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Jun 2 14:45:10 2015 +0200
jscript: Added beginning support for 'automagic' event binding feature.
---
dlls/jscript/compile.c | 18 ++++++++++----- dlls/jscript/engine.c | 60 ++++++++++++++++++++++++++++++++++++++++++-------- dlls/jscript/engine.h | 1 + dlls/jscript/lex.c | 8 ++++++- dlls/jscript/parser.h | 1 + dlls/jscript/parser.y | 17 +++++++++----- 6 files changed, 84 insertions(+), 21 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index f056be1..52e6b66 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -862,7 +862,7 @@ static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_express ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
/* FIXME: not exactly right */ - if(expr->identifier) { + if(expr->identifier && !expr->event_target) { ctx->func->func_cnt++; return push_instr_bstr(ctx, OP_ident, expr->identifier); } @@ -1865,10 +1865,18 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
func->instr_off = off;
- if(func_expr && func_expr->identifier) { - func->name = compiler_alloc_bstr(ctx, func_expr->identifier); - if(!func->name) - return E_OUTOFMEMORY; + if(func_expr) { + if(func_expr->identifier) { + func->name = compiler_alloc_bstr(ctx, func_expr->identifier); + if(!func->name) + return E_OUTOFMEMORY; + } + + if(func_expr->event_target) { + func->event_target = compiler_alloc_bstr(ctx, func_expr->event_target); + if(!func->event_target) + return E_OUTOFMEMORY; + } }
if(func_expr) { diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index de60755..ca08d91 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -511,14 +511,16 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re
TRACE("%s\n", debugstr_w(identifier));
- for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) { - if(scope->jsobj) - hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id); - else - hres = disp_get_id(ctx, scope->obj, identifier, identifier, fdexNameImplicit, &id); - if(SUCCEEDED(hres)) { - exprval_set_idref(ret, scope->obj, id); - return S_OK; + if(ctx->exec_ctx) { + for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) { + if(scope->jsobj) + hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id); + else + hres = disp_get_id(ctx, scope->obj, identifier, identifier, fdexNameImplicit, &id); + if(SUCCEEDED(hres)) { + exprval_set_idref(ret, scope->obj, id); + return S_OK; + } } }
@@ -2504,6 +2506,43 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code return S_OK; }
+static HRESULT bind_event_target(script_ctx_t *ctx, function_code_t *func, jsdisp_t *func_obj) +{ + IBindEventHandler *target; + exprval_t exprval; + IDispatch *disp; + jsval_t v; + HRESULT hres; + + hres = identifier_eval(ctx, func->event_target, &exprval); + if(FAILED(hres)) + return hres; + + hres = exprval_to_value(ctx, &exprval, &v); + exprval_release(&exprval); + if(FAILED(hres)) + return hres; + + if(!is_object_instance(v)) { + FIXME("Can't bind to %s\n", debugstr_jsval(v)); + jsval_release(v); + } + + disp = get_object(v); + hres = IDispatch_QueryInterface(disp, &IID_IBindEventHandler, (void**)&target); + if(SUCCEEDED(hres)) { + hres = IBindEventHandler_BindHandler(target, func->name, (IDispatch*)&func_obj->IDispatchEx_iface); + IBindEventHandler_Release(target); + if(FAILED(hres)) + WARN("BindEvent failed: %08x\n", hres); + }else { + FIXME("No IBindEventHandler, not yet supported binding\n"); + } + + IDispatch_Release(disp); + return hres; +} + HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BOOL from_eval, jsval_t *ret) { exec_ctx_t *prev_ctx; @@ -2521,7 +2560,10 @@ HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BO if(FAILED(hres)) return hres;
- hres = jsdisp_propput_name(ctx->var_disp, func->funcs[i].name, jsval_obj(func_obj)); + if(func->funcs[i].event_target) + hres = bind_event_target(ctx->script, func->funcs+i, func_obj); + else + hres = jsdisp_propput_name(ctx->var_disp, func->funcs[i].name, jsval_obj(func_obj)); jsdisp_release(func_obj); if(FAILED(hres)) return hres; diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index bd49c99..dd8ed4c 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -127,6 +127,7 @@ typedef struct {
typedef struct _function_code_t { BSTR name; + BSTR event_target; unsigned instr_off;
const WCHAR *source; diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c index af4b24b..57ab033 100644 --- a/dlls/jscript/lex.c +++ b/dlls/jscript/lex.c @@ -590,7 +590,6 @@ static int next_token(parser_ctx_t *ctx, void *lval) case ',': case '~': case '?': - case ':': return *ctx->ptr++;
case '}': @@ -786,6 +785,13 @@ static int next_token(parser_ctx_t *ctx, void *lval) } return '/';
+ case ':': + if(++ctx->ptr < ctx->end && *ctx->ptr == ':') { + ctx->ptr++; + return kDCOL; + } + return ':'; + case '"': case ''': return parse_string_literal(ctx, lval, *ctx->ptr); diff --git a/dlls/jscript/parser.h b/dlls/jscript/parser.h index ab5744a..f8d404f 100644 --- a/dlls/jscript/parser.h +++ b/dlls/jscript/parser.h @@ -285,6 +285,7 @@ struct _source_elements_t { typedef struct _function_expression_t { expression_t expr; const WCHAR *identifier; + const WCHAR *event_target; parameter_t *parameter_list; source_elements_t *source_elements; const WCHAR *src_str; diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 7b36b11..59e6757 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -120,7 +120,7 @@ static parameter_list_t *parameter_list_add(parser_ctx_t*,parameter_list_t*,cons
static void *new_expression(parser_ctx_t *ctx,expression_type_t,size_t); static expression_t *new_function_expression(parser_ctx_t*,const WCHAR*,parameter_list_t*, - source_elements_t*,const WCHAR*,DWORD); + source_elements_t*,const WCHAR*,const WCHAR*,DWORD); static expression_t *new_binary_expression(parser_ctx_t*,expression_type_t,expression_t*,expression_t*); static expression_t *new_unary_expression(parser_ctx_t*,expression_type_t,expression_t*); static expression_t *new_conditional_expression(parser_ctx_t*,expression_t*,expression_t*,expression_t*); @@ -166,7 +166,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state /* keywords */ %token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kIN %token kINSTANCEOF kNEW kNULL kRETURN kSWITCH kTHIS kTHROW kTRUE kFALSE kTRY kTYPEOF kVAR kVOID kWHILE kWITH -%token tANDAND tOROR tINC tDEC tHTMLCOMMENT kDIVEQ +%token tANDAND tOROR tINC tDEC tHTMLCOMMENT kDIVEQ kDCOL
%token <srcptr> kFUNCTION '}'
@@ -264,8 +264,12 @@ SourceElements
/* ECMA-262 3rd Edition 13 */ FunctionExpression - : KFunction Identifier_opt left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' - { $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); } + : KFunction left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + { $$ = new_function_expression(ctx, NULL, $3, $6, NULL, $1, $7-$1+1); } + | KFunction tIdentifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + { $$ = new_function_expression(ctx, $2, $4, $7, NULL, $1, $8-$1+1); } + | KFunction tIdentifier kDCOL tIdentifier left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' + { $$ = new_function_expression(ctx, $4, $6, $9, $2, $1, $10-$1+1); }
KFunction : kFUNCTION { $$ = $1; } @@ -1300,14 +1304,15 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t return list; }
-static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, - parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len) +static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, parameter_list_t *parameter_list, + source_elements_t *source_elements, const WCHAR *event_target, const WCHAR *src_str, DWORD src_len) { function_expression_t *ret = new_expression(ctx, EXPR_FUNC, sizeof(*ret));
ret->identifier = identifier; ret->parameter_list = parameter_list ? parameter_list->head : NULL; ret->source_elements = source_elements; + ret->event_target = event_target; ret->src_str = src_str; ret->src_len = src_len; ret->next = NULL;