jscript: Use jsval_t instead of VARIANT for stack values.

This commit is contained in:
Jacek Caban 2012-09-17 15:17:02 +02:00 committed by Alexandre Julliard
parent 847aebdc87
commit 16b2b019b8
7 changed files with 483 additions and 654 deletions

View File

@ -971,19 +971,6 @@ jsdisp_t *iface_to_jsdisp(IUnknown *iface)
return ret;
}
static void ensure_retval_type(VARIANT *v)
{
switch(V_VT(v)) {
case VT_I2:
V_VT(v) = VT_I4;
V_I4(v) = V_I2(v);
break;
case VT_INT:
V_VT(v) = VT_I4;
V_I4(v) = V_INT(v);
}
}
HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
{
dispex_prop_t *prop;
@ -1062,11 +1049,11 @@ HRESULT jsdisp_call_name(jsdisp_t *disp, const WCHAR *name, WORD flags, unsigned
}
HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, unsigned argc, jsval_t *argv,
VARIANT *retv, jsexcept_t *ei)
jsval_t *ret, jsexcept_t *ei)
{
IDispatchEx *dispex;
jsdisp_t *jsdisp;
VARIANT buf[6];
VARIANT buf[6], retv;
DISPPARAMS dp;
unsigned i;
HRESULT hres;
@ -1078,13 +1065,21 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
return E_FAIL;
}
hres = jsdisp_call(jsdisp, id, flags, argc, argv, retv, ei);
V_VT(&retv) = VT_EMPTY;
hres = jsdisp_call(jsdisp, id, flags, argc, argv, ret ? &retv : NULL, ei);
jsdisp_release(jsdisp);
if(FAILED(hres))
return hres;
if(ret) {
hres = variant_to_jsval(&retv, ret);
VariantClear(&retv);
}
return hres;
}
memset(ei, 0, sizeof(*ei));
if(retv && argc)
if(ret && argc)
flags |= DISPATCH_PROPERTYGET;
dp.cArgs = argc;
@ -1118,12 +1113,11 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
}
}
if(retv)
V_VT(retv) = VT_EMPTY;
V_VT(&retv) = VT_EMPTY;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, &dp, retv, &ei->ei, &ctx->jscaller->IServiceProvider_iface);
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ei->ei,
&ctx->jscaller->IServiceProvider_iface);
IDispatchEx_Release(dispex);
}else {
UINT err = 0;
@ -1134,7 +1128,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
}
TRACE("using IDispatch\n");
hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, retv, &ei->ei, &err);
hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, flags, &dp, ret ? &retv : NULL, &ei->ei, &err);
}
for(i=0; i<argc; i++)
@ -1144,9 +1138,11 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
if(FAILED(hres))
return hres;
if(retv)
ensure_retval_type(retv);
return S_OK;
if(ret) {
hres = variant_to_jsval(&retv, ret);
VariantClear(&retv);
}
return hres;
}
HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv,
@ -1290,7 +1286,7 @@ HRESULT jsdisp_propput_idx(jsdisp_t *obj, DWORD idx, jsval_t val, jsexcept_t *ei
return jsdisp_propput_name(obj, buf, val, ei);
}
HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *var, jsexcept_t *ei)
HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val, jsexcept_t *ei)
{
jsdisp_t *jsdisp;
HRESULT hres;
@ -1298,11 +1294,6 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *var
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
dispex_prop_t *prop;
jsval_t val;
hres = variant_to_jsval(var, &val);
if(FAILED(hres))
return hres;
prop = get_prop(jsdisp, id);
if(prop)
@ -1310,13 +1301,17 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *var
else
hres = DISP_E_MEMBERNOTFOUND;
jsval_release(val);
jsdisp_release(jsdisp);
}else {
DISPID dispid = DISPID_PROPERTYPUT;
DISPPARAMS dp = {var, &dispid, 1, 1};
VARIANT var;
DISPPARAMS dp = {&var, &dispid, 1, 1};
IDispatchEx *dispex;
hres = jsval_to_variant(val, &var);
if(FAILED(hres))
return hres;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei,
@ -1328,6 +1323,8 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *var
TRACE("using IDispatch\n");
hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, DISPATCH_PROPERTYPUT, &dp, NULL, &ei->ei, &err);
}
VariantClear(&var);
}
return hres;
@ -1386,41 +1383,37 @@ HRESULT jsdisp_propget(jsdisp_t *jsdisp, DISPID id, jsval_t *val, jsexcept_t *ei
return prop_get(jsdisp, prop, &dp, val, ei, NULL);
}
HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, VARIANT *val, jsexcept_t *ei)
HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val, jsexcept_t *ei)
{
DISPPARAMS dp = {NULL,NULL,0,0};
IDispatchEx *dispex;
jsdisp_t *jsdisp;
VARIANT var;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) {
jsval_t v;
hres = jsdisp_propget(jsdisp, id, &v, ei);
hres = jsdisp_propget(jsdisp, id, val, ei);
jsdisp_release(jsdisp);
if(SUCCEEDED(hres)) {
hres = jsval_to_variant(v, val);
jsval_release(v);
}
return hres;
}
V_VT(&var) = VT_EMPTY;
hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
if(SUCCEEDED(hres)) {
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei,
hres = IDispatchEx_InvokeEx(dispex, id, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ei->ei,
&ctx->jscaller->IServiceProvider_iface);
IDispatchEx_Release(dispex);
}else {
ULONG err = 0;
TRACE("using IDispatch\n");
hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, val, &ei->ei, &err);
hres = IDispatch_Invoke(disp, id, &IID_NULL, ctx->lcid, INVOKE_PROPERTYGET, &dp, &var, &ei->ei, &err);
}
if(FAILED(hres))
return hres;
ensure_retval_type(val);
return S_OK;
return variant_to_jsval(&var, val);
}
HRESULT jsdisp_delete_idx(jsdisp_t *obj, DWORD idx)

File diff suppressed because it is too large Load Diff

View File

@ -230,7 +230,7 @@ struct _exec_ctx_t {
function_code_t *func_code;
BOOL is_global;
VARIANT *stack;
jsval_t *stack;
unsigned stack_size;
unsigned top;
except_frame_t *except_frame;
@ -246,7 +246,7 @@ static inline void exec_addref(exec_ctx_t *ctx)
void exec_release(exec_ctx_t*) DECLSPEC_HIDDEN;
HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,jsdisp_t*,scope_chain_t*,BOOL,exec_ctx_t**) DECLSPEC_HIDDEN;
HRESULT exec_source(exec_ctx_t*,bytecode_t*,function_code_t*,BOOL,jsexcept_t*,VARIANT*) DECLSPEC_HIDDEN;
HRESULT exec_source(exec_ctx_t*,bytecode_t*,function_code_t*,BOOL,jsexcept_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN;
typedef enum {
@ -396,12 +396,12 @@ typedef struct {
typedef struct {
enum {
EXPRVAL_VARIANT,
EXPRVAL_JSVAL,
EXPRVAL_IDREF,
EXPRVAL_INVALID
} type;
union {
VARIANT var;
jsval_t val;
struct {
IDispatch *disp;
DISPID id;

View File

@ -180,16 +180,11 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
jsdisp_release(var_disp);
if(SUCCEEDED(hres)) {
jsdisp_t *prev_args;
VARIANT retv;
prev_args = function->arguments;
function->arguments = arg_disp;
hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, ei, r ? &retv : NULL);
hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, ei, r);
function->arguments = prev_args;
if(SUCCEEDED(hres) && r) {
hres = variant_to_jsval(&retv, r);
VariantClear(&retv);
}
}
jsdisp_release(arg_disp);

View File

@ -349,7 +349,6 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
jsval_t *r, jsexcept_t *ei)
{
bytecode_t *code;
VARIANT retv;
HRESULT hres;
TRACE("\n");
@ -378,15 +377,8 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
return throw_syntax_error(ctx, ei, hres, NULL);
}
hres = exec_source(ctx->exec_ctx, code, &code->global_code, TRUE, ei, r ? &retv : NULL);
hres = exec_source(ctx->exec_ctx, code, &code->global_code, TRUE, ei, r);
release_bytecode(code);
if(FAILED(hres))
return hres;
if(r) {
hres = variant_to_jsval(&retv, r);
VariantClear(&retv);
}
return hres;
}

View File

@ -208,13 +208,13 @@ HRESULT create_dispex(script_ctx_t*,const builtin_info_t*,jsdisp_t*,jsdisp_t**)
HRESULT init_dispex(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN;
HRESULT init_dispex_from_constr(jsdisp_t*,script_ctx_t*,const builtin_info_t*,jsdisp_t*) DECLSPEC_HIDDEN;
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT disp_call(script_ctx_t*,IDispatch*,DISPID,WORD,unsigned,jsval_t*,jsval_t*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT disp_call_value(script_ctx_t*,IDispatch*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_call_value(jsdisp_t*,IDispatch*,WORD,unsigned,jsval_t*,jsval_t*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_call(jsdisp_t*,DISPID,WORD,unsigned,jsval_t*,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_call_name(jsdisp_t*,const WCHAR*,WORD,unsigned,jsval_t*,jsval_t*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,VARIANT*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT disp_propget(script_ctx_t*,IDispatch*,DISPID,jsval_t*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT disp_propput(script_ctx_t*,IDispatch*,DISPID,jsval_t,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_propget(jsdisp_t*,DISPID,jsval_t*,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_propput_name(jsdisp_t*,const WCHAR*,jsval_t,jsexcept_t*) DECLSPEC_HIDDEN;
HRESULT jsdisp_propput_const(jsdisp_t*,const WCHAR*,VARIANT*) DECLSPEC_HIDDEN;
@ -259,6 +259,7 @@ typedef enum {
} hint_t;
HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*, hint_t) DECLSPEC_HIDDEN;
HRESULT to_primitive_jsval(script_ctx_t*,jsval_t,jsexcept_t*,jsval_t*, hint_t) DECLSPEC_HIDDEN;
HRESULT to_boolean(VARIANT*,VARIANT_BOOL*) DECLSPEC_HIDDEN;
HRESULT to_boolean_jsval(jsval_t,BOOL*) DECLSPEC_HIDDEN;
HRESULT to_number(script_ctx_t*,VARIANT*,jsexcept_t*,double*) DECLSPEC_HIDDEN;

View File

@ -52,6 +52,8 @@ const char *debugstr_variant(const VARIANT *v)
return wine_dbg_sprintf("{VT_DISPATCH: %p}", V_DISPATCH(v));
case VT_BOOL:
return wine_dbg_sprintf("{VT_BOOL: %x}", V_BOOL(v));
case VT_ARRAY|VT_VARIANT:
return "{VT_ARRAY|VT_VARIANT: ...}";
default:
return wine_dbg_sprintf("{vt %d}", V_VT(v));
}
@ -241,7 +243,7 @@ HRESULT jsval_variant(jsval_t *val, VARIANT *var)
if(!val->u.v)
return E_OUTOFMEMORY;
V_VT(val->u.v) = VT_EMPTY;
V_VT(val->u.v) = VT_EMPTY;
hres = VariantCopy(val->u.v, var);
if(FAILED(hres))
heap_free(val->u.v);
@ -357,6 +359,7 @@ HRESULT jsval_to_variant(jsval_t val, VARIANT *retv)
V_BOOL(retv) = val.u.b ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
case JSV_VARIANT:
V_VT(retv) = VT_EMPTY;
return VariantCopy(retv, val.u.v);
}
@ -394,8 +397,16 @@ HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret
jsdisp = iface_to_jsdisp((IUnknown*)V_DISPATCH(v));
if(!jsdisp) {
V_VT(ret) = VT_EMPTY;
return disp_propget(ctx, V_DISPATCH(v), DISPID_VALUE, ret, ei);
jsval_t val;
HRESULT hres;
hres = disp_propget(ctx, V_DISPATCH(v), DISPID_VALUE, &val, ei);
if(FAILED(hres))
return hres;
hres = jsval_to_variant(val, ret);
jsval_release(val);
return hres;
}
if(hint == NO_HINT)
@ -451,6 +462,28 @@ HRESULT to_primitive(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, VARIANT *ret
return S_OK;
}
/* ECMA-262 3rd Edition 9.1 */
HRESULT to_primitive_jsval(script_ctx_t *ctx, jsval_t val, jsexcept_t *ei, jsval_t *ret, hint_t hint)
{
if(is_object_instance(val)) {
VARIANT var, retv;
HRESULT hres;
V_VT(&var) = VT_DISPATCH;
V_DISPATCH(&var) = get_object(val);
hres = to_primitive(ctx, &var, ei, &retv, hint);
if(FAILED(hres))
return hres;
hres = variant_to_jsval(&retv, ret);
VariantClear(&retv);
return hres;
}
return jsval_copy(val, ret);
}
/* ECMA-262 3rd Edition 9.2 */
HRESULT to_boolean(VARIANT *v, VARIANT_BOOL *b)
{
@ -961,9 +994,7 @@ HRESULT to_object_jsval(script_ctx_t *ctx, jsval_t v, IDispatch **disp)
if(FAILED(hres))
return hres;
hres = to_object(ctx, &var, disp);
VariantClear(&var);
return hres;
return to_object(ctx, &var, disp);
}
HRESULT variant_change_type(script_ctx_t *ctx, VARIANT *dst, VARIANT *src, VARTYPE vt)