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

This commit is contained in:
Jacek Caban 2015-06-02 14:45:10 +02:00 committed by Alexandre Julliard
parent b75cd7e2f0
commit 170bb3771f
6 changed files with 84 additions and 21 deletions

View File

@ -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); ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
/* FIXME: not exactly right */ /* FIXME: not exactly right */
if(expr->identifier) { if(expr->identifier && !expr->event_target) {
ctx->func->func_cnt++; ctx->func->func_cnt++;
return push_instr_bstr(ctx, OP_ident, expr->identifier); return push_instr_bstr(ctx, OP_ident, expr->identifier);
} }
@ -1865,12 +1865,20 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
func->instr_off = off; func->instr_off = off;
if(func_expr && func_expr->identifier) { if(func_expr) {
if(func_expr->identifier) {
func->name = compiler_alloc_bstr(ctx, func_expr->identifier); func->name = compiler_alloc_bstr(ctx, func_expr->identifier);
if(!func->name) if(!func->name)
return E_OUTOFMEMORY; 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) { if(func_expr) {
parameter_t *param_iter; parameter_t *param_iter;

View File

@ -511,6 +511,7 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re
TRACE("%s\n", debugstr_w(identifier)); TRACE("%s\n", debugstr_w(identifier));
if(ctx->exec_ctx) {
for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) { for(scope = ctx->exec_ctx->scope_chain; scope; scope = scope->next) {
if(scope->jsobj) if(scope->jsobj)
hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id); hres = jsdisp_get_id(scope->jsobj, identifier, fdexNameImplicit, &id);
@ -521,6 +522,7 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re
return S_OK; return S_OK;
} }
} }
}
hres = jsdisp_get_id(ctx->global, identifier, 0, &id); hres = jsdisp_get_id(ctx->global, identifier, 0, &id);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
@ -2504,6 +2506,43 @@ static HRESULT enter_bytecode(script_ctx_t *ctx, bytecode_t *code, function_code
return S_OK; 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) 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; exec_ctx_t *prev_ctx;
@ -2521,6 +2560,9 @@ HRESULT exec_source(exec_ctx_t *ctx, bytecode_t *code, function_code_t *func, BO
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
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)); hres = jsdisp_propput_name(ctx->var_disp, func->funcs[i].name, jsval_obj(func_obj));
jsdisp_release(func_obj); jsdisp_release(func_obj);
if(FAILED(hres)) if(FAILED(hres))

View File

@ -127,6 +127,7 @@ typedef struct {
typedef struct _function_code_t { typedef struct _function_code_t {
BSTR name; BSTR name;
BSTR event_target;
unsigned instr_off; unsigned instr_off;
const WCHAR *source; const WCHAR *source;

View File

@ -590,7 +590,6 @@ static int next_token(parser_ctx_t *ctx, void *lval)
case ',': case ',':
case '~': case '~':
case '?': case '?':
case ':':
return *ctx->ptr++; return *ctx->ptr++;
case '}': case '}':
@ -786,6 +785,13 @@ static int next_token(parser_ctx_t *ctx, void *lval)
} }
return '/'; return '/';
case ':':
if(++ctx->ptr < ctx->end && *ctx->ptr == ':') {
ctx->ptr++;
return kDCOL;
}
return ':';
case '\"': case '\"':
case '\'': case '\'':
return parse_string_literal(ctx, lval, *ctx->ptr); return parse_string_literal(ctx, lval, *ctx->ptr);

View File

@ -285,6 +285,7 @@ struct _source_elements_t {
typedef struct _function_expression_t { typedef struct _function_expression_t {
expression_t expr; expression_t expr;
const WCHAR *identifier; const WCHAR *identifier;
const WCHAR *event_target;
parameter_t *parameter_list; parameter_t *parameter_list;
source_elements_t *source_elements; source_elements_t *source_elements;
const WCHAR *src_str; const WCHAR *src_str;

View File

@ -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 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*, 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_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_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*); 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 */ /* keywords */
%token kBREAK kCASE kCATCH kCONTINUE kDEFAULT kDELETE kDO kELSE kIF kFINALLY kFOR kIN %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 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 '}' %token <srcptr> kFUNCTION '}'
@ -264,8 +264,12 @@ SourceElements
/* ECMA-262 3rd Edition 13 */ /* ECMA-262 3rd Edition 13 */
FunctionExpression FunctionExpression
: KFunction Identifier_opt left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}' : KFunction left_bracket FormalParameterList_opt right_bracket '{' FunctionBody '}'
{ $$ = new_function_expression(ctx, $2, $4, $7, $1, $8-$1+1); } { $$ = 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
: kFUNCTION { $$ = $1; } : kFUNCTION { $$ = $1; }
@ -1300,14 +1304,15 @@ static parameter_list_t *parameter_list_add(parser_ctx_t *ctx, parameter_list_t
return list; return list;
} }
static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, static expression_t *new_function_expression(parser_ctx_t *ctx, const WCHAR *identifier, parameter_list_t *parameter_list,
parameter_list_t *parameter_list, source_elements_t *source_elements, const WCHAR *src_str, DWORD src_len) 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)); function_expression_t *ret = new_expression(ctx, EXPR_FUNC, sizeof(*ret));
ret->identifier = identifier; ret->identifier = identifier;
ret->parameter_list = parameter_list ? parameter_list->head : NULL; ret->parameter_list = parameter_list ? parameter_list->head : NULL;
ret->source_elements = source_elements; ret->source_elements = source_elements;
ret->event_target = event_target;
ret->src_str = src_str; ret->src_str = src_str;
ret->src_len = src_len; ret->src_len = src_len;
ret->next = NULL; ret->next = NULL;