Jacek Caban : jscript: Added beginning support for 'automagic' event binding feature.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jun 3 09:43:08 CDT 2015


Module: wine
Branch: master
Commit: 170bb3771f43f1120435e98ea38543d5a667f9bc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=170bb3771f43f1120435e98ea38543d5a667f9bc

Author: Jacek Caban <jacek at 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;




More information about the wine-cvs mailing list