vbscript: Evaluate object expression before value expression in member assignment.
This commit is contained in:
parent
434700bf6b
commit
1e5c2134f1
|
@ -697,10 +697,6 @@ static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *
|
||||||
vbsop_t op;
|
vbsop_t op;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
hres = compile_expression(ctx, stat->value_expr);
|
|
||||||
if(FAILED(hres))
|
|
||||||
return hres;
|
|
||||||
|
|
||||||
if(stat->member_expr->obj_expr) {
|
if(stat->member_expr->obj_expr) {
|
||||||
hres = compile_expression(ctx, stat->member_expr->obj_expr);
|
hres = compile_expression(ctx, stat->member_expr->obj_expr);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
|
@ -711,6 +707,10 @@ static HRESULT compile_assign_statement(compile_ctx_t *ctx, assign_statement_t *
|
||||||
op = is_set ? OP_set_ident : OP_assign_ident;
|
op = is_set ? OP_set_ident : OP_assign_ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hres = compile_expression(ctx, stat->value_expr);
|
||||||
|
if(FAILED(hres))
|
||||||
|
return hres;
|
||||||
|
|
||||||
hres = compile_args(ctx, stat->member_expr->args, &args_cnt);
|
hres = compile_args(ctx, stat->member_expr->args, &args_cnt);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
|
@ -348,6 +348,33 @@ static HRESULT stack_pop_disp(exec_ctx_t *ctx, IDispatch **ret)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT stack_assume_disp(exec_ctx_t *ctx, unsigned n, IDispatch **disp)
|
||||||
|
{
|
||||||
|
VARIANT *v = stack_top(ctx, n), *ref;
|
||||||
|
|
||||||
|
if(V_VT(v) != VT_DISPATCH) {
|
||||||
|
if(V_VT(v) != (VT_VARIANT|VT_BYREF)) {
|
||||||
|
FIXME("not supported type: %s\n", debugstr_variant(v));
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = V_VARIANTREF(v);
|
||||||
|
if(V_VT(ref) != VT_DISPATCH) {
|
||||||
|
FIXME("not disp %s\n", debugstr_variant(ref));
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
V_VT(v) = VT_DISPATCH;
|
||||||
|
V_DISPATCH(v) = V_DISPATCH(ref);
|
||||||
|
if(V_DISPATCH(v))
|
||||||
|
IDispatch_AddRef(V_DISPATCH(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(disp)
|
||||||
|
*disp = V_DISPATCH(v);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void instr_jmp(exec_ctx_t *ctx, unsigned addr)
|
static inline void instr_jmp(exec_ctx_t *ctx, unsigned addr)
|
||||||
{
|
{
|
||||||
ctx->instr = ctx->code->instrs + addr;
|
ctx->instr = ctx->code->instrs + addr;
|
||||||
|
@ -623,7 +650,7 @@ static HRESULT interp_assign_member(exec_ctx_t *ctx)
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = stack_pop_disp(ctx, &obj);
|
hres = stack_assume_disp(ctx, arg_cnt+1, &obj);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
|
@ -633,25 +660,25 @@ static HRESULT interp_assign_member(exec_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = stack_pop_val(ctx, &val);
|
hres = stack_pop_val(ctx, &val);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres))
|
||||||
IDispatch_Release(obj);
|
|
||||||
return hres;
|
return hres;
|
||||||
}
|
|
||||||
|
|
||||||
hres = disp_get_id(obj, identifier, VBDISP_LET, FALSE, &id);
|
hres = disp_get_id(obj, identifier, VBDISP_LET, FALSE, &id);
|
||||||
if(SUCCEEDED(hres))
|
if(SUCCEEDED(hres))
|
||||||
hres = disp_propput(ctx->script, obj, id, val.v);
|
hres = disp_propput(ctx->script, obj, id, val.v);
|
||||||
|
|
||||||
release_val(&val);
|
release_val(&val);
|
||||||
IDispatch_Release(obj);
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
|
stack_popn(ctx, 1);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT interp_set_member(exec_ctx_t *ctx)
|
static HRESULT interp_set_member(exec_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
BSTR identifier = ctx->instr->arg1.bstr;
|
BSTR identifier = ctx->instr->arg1.bstr;
|
||||||
const unsigned arg_cnt = ctx->instr->arg2.uint;
|
const unsigned arg_cnt = ctx->instr->arg2.uint;
|
||||||
IDispatch *obj, *val;
|
IDispatch *obj;
|
||||||
DISPID id;
|
DISPID id;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
|
@ -662,7 +689,7 @@ static HRESULT interp_set_member(exec_ctx_t *ctx)
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = stack_pop_disp(ctx, &obj);
|
hres = stack_assume_disp(ctx, 1, &obj);
|
||||||
if(FAILED(hres))
|
if(FAILED(hres))
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
|
@ -671,25 +698,18 @@ static HRESULT interp_set_member(exec_ctx_t *ctx)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hres = stack_pop_disp(ctx, &val);
|
hres = stack_assume_disp(ctx, 0, NULL);
|
||||||
if(FAILED(hres)) {
|
if(FAILED(hres))
|
||||||
IDispatch_Release(obj);
|
|
||||||
return hres;
|
return hres;
|
||||||
}
|
|
||||||
|
|
||||||
hres = disp_get_id(obj, identifier, VBDISP_SET, FALSE, &id);
|
hres = disp_get_id(obj, identifier, VBDISP_SET, FALSE, &id);
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres))
|
||||||
VARIANT v;
|
hres = disp_propput(ctx->script, obj, id, stack_top(ctx, 0));
|
||||||
|
if(FAILED(hres))
|
||||||
V_VT(&v) = VT_DISPATCH;
|
|
||||||
V_DISPATCH(&v) = val;
|
|
||||||
hres = disp_propput(ctx->script, obj, id, &v);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(val)
|
|
||||||
IDispatch_Release(val);
|
|
||||||
IDispatch_Release(obj);
|
|
||||||
return hres;
|
return hres;
|
||||||
|
|
||||||
|
stack_popn(ctx, 2);
|
||||||
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT interp_const(exec_ctx_t *ctx)
|
static HRESULT interp_const(exec_ctx_t *ctx)
|
||||||
|
|
Loading…
Reference in New Issue