From 3caf287630279a2658dd99c0be0f9cf387a49132 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 13 Dec 2011 11:57:11 +0100 Subject: [PATCH] jscript: Use bytecode for typeof expression implementation. --- dlls/jscript/compile.c | 23 +++++++ dlls/jscript/engine.c | 135 +++++++++++++++++++++++++++-------------- dlls/jscript/engine.h | 4 +- dlls/jscript/parser.y | 2 +- 4 files changed, 118 insertions(+), 46 deletions(-) diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 0d4ce791677..ff53c90be6f 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -534,6 +534,27 @@ static HRESULT compile_assign_expression(compiler_ctx_t *ctx, binary_expression_ return S_OK; } +static HRESULT compile_typeof_expression(compiler_ctx_t *ctx, unary_expression_t *expr) +{ + jsop_t op; + HRESULT hres; + + if(is_memberid_expr(expr->expression->type)) { + if(expr->expression->type == EXPR_IDENT) + return push_instr_str(ctx, OP_typeofident, ((identifier_expression_t*)expr->expression)->identifier); + + op = OP_typeofid; + hres = compile_memberid_expression(ctx, expr->expression, 0); + }else { + op = OP_typeof; + hres = compile_expression(ctx, expr->expression); + } + if(FAILED(hres)) + return hres; + + return push_instr(ctx, op) == -1 ? E_OUTOFMEMORY : S_OK; +} + static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal) { switch(literal->type) { @@ -707,6 +728,8 @@ static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr, return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_sub); case EXPR_THIS: return push_instr(ctx, OP_this) == -1 ? E_OUTOFMEMORY : S_OK; + case EXPR_TYPEOF: + return compile_typeof_expression(ctx, (unary_expression_t*)expr); case EXPR_VOID: return compile_unary_expression(ctx, (unary_expression_t*)expr, OP_void); case EXPR_BXOR: diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index da02052dd74..e399aa8e7d2 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -32,6 +32,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); #define EXPR_NOVAL 0x0001 #define EXPR_NEWREF 0x0002 +static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0}; +static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0}; +static const WCHAR numberW[] = {'n','u','m','b','e','r',0}; +static const WCHAR objectW[] = {'o','b','j','e','c','t',0}; +static const WCHAR stringW[] = {'s','t','r','i','n','g',0}; +static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; +static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0}; + struct _return_type_t { enum{ RT_NORMAL, @@ -102,6 +110,15 @@ static inline HRESULT stack_push_int(exec_ctx_t *ctx, INT n) return stack_push(ctx, &v); } +static inline HRESULT stack_push_string(exec_ctx_t *ctx, const WCHAR *str) +{ + VARIANT v; + + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = SysAllocString(str); + return V_BSTR(&v) ? stack_push(ctx, &v) : E_OUTOFMEMORY; +} + static HRESULT stack_push_objid(exec_ctx_t *ctx, IDispatch *disp, DISPID id) { VARIANT v; @@ -2456,34 +2473,9 @@ static HRESULT interp_void(exec_ctx_t *ctx) } /* ECMA-262 3rd Edition 11.4.3 */ -static HRESULT typeof_exprval(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t *ei, const WCHAR **ret) +static HRESULT typeof_string(VARIANT *v, const WCHAR **ret) { - VARIANT val; - HRESULT hres; - - static const WCHAR booleanW[] = {'b','o','o','l','e','a','n',0}; - static const WCHAR functionW[] = {'f','u','n','c','t','i','o','n',0}; - static const WCHAR numberW[] = {'n','u','m','b','e','r',0}; - static const WCHAR objectW[] = {'o','b','j','e','c','t',0}; - static const WCHAR stringW[] = {'s','t','r','i','n','g',0}; - static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; - static const WCHAR unknownW[] = {'u','n','k','n','o','w','n',0}; - - if(exprval->type == EXPRVAL_INVALID) { - *ret = undefinedW; - return S_OK; - } - - hres = exprval_to_value(ctx, exprval, ei, &val); - if(FAILED(hres)) { - if(exprval->type == EXPRVAL_IDREF) { - *ret = unknownW; - return S_OK; - } - return hres; - } - - switch(V_VT(&val)) { + switch(V_VT(v)) { case VT_EMPTY: *ret = undefinedW; break; @@ -2503,7 +2495,7 @@ static HRESULT typeof_exprval(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t case VT_DISPATCH: { jsdisp_t *dispex; - if(V_DISPATCH(&val) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(&val)))) { + if(V_DISPATCH(v) && (dispex = iface_to_jsdisp((IUnknown*)V_DISPATCH(v)))) { *ret = is_class(dispex, JSCLASS_FUNCTION) ? functionW : objectW; jsdisp_release(dispex); }else { @@ -2512,39 +2504,94 @@ static HRESULT typeof_exprval(script_ctx_t *ctx, exprval_t *exprval, jsexcept_t break; } default: - FIXME("unhandled vt %d\n", V_VT(&val)); - hres = E_NOTIMPL; + FIXME("unhandled vt %d\n", V_VT(v)); + return E_NOTIMPL; } - VariantClear(&val); - return hres; + return S_OK; } -HRESULT typeof_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret) +/* ECMA-262 3rd Edition 11.4.3 */ +static HRESULT interp_typeofid(exec_ctx_t *ctx) { - unary_expression_t *expr = (unary_expression_t*)_expr; - const WCHAR *str = NULL; - exprval_t exprval; + const WCHAR *ret; + IDispatch *obj; + VARIANT v; + DISPID id; HRESULT hres; + static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; + TRACE("\n"); - hres = expr_eval(ctx, expr->expression, 0, ei, &exprval); + obj = stack_pop_objid(ctx, &id); + if(!obj) + return stack_push_string(ctx, undefinedW); + + V_VT(&v) = VT_EMPTY; + hres = disp_propget(ctx->parser->script, obj, id, &v, &ctx->ei, NULL/*FIXME*/); + IDispatch_Release(obj); + if(FAILED(hres)) + return stack_push_string(ctx, unknownW); + + hres = typeof_string(&v, &ret); + VariantClear(&v); if(FAILED(hres)) return hres; - hres = typeof_exprval(ctx, &exprval, ei, &str); + return stack_push_string(ctx, ret); +} + +/* ECMA-262 3rd Edition 11.4.3 */ +static HRESULT interp_typeofident(exec_ctx_t *ctx) +{ + const BSTR arg = ctx->parser->code->instrs[ctx->ip].arg1.bstr; + exprval_t exprval; + const WCHAR *ret; + VARIANT v; + HRESULT hres; + + TRACE("%s\n", debugstr_w(arg)); + + hres = identifier_eval(ctx->parser->script, arg, 0, &ctx->ei, &exprval); + if(FAILED(hres)) + return hres; + + if(exprval.type == EXPRVAL_INVALID) { + hres = stack_push_string(ctx, undefinedW); + exprval_release(&exprval); + return hres; + } + + hres = exprval_to_value(ctx->parser->script, &exprval, &ctx->ei, &v); exprval_release(&exprval); if(FAILED(hres)) return hres; - ret->type = EXPRVAL_VARIANT; - V_VT(&ret->u.var) = VT_BSTR; - V_BSTR(&ret->u.var) = SysAllocString(str); - if(!V_BSTR(&ret->u.var)) - return E_OUTOFMEMORY; + hres = typeof_string(&v, &ret); + VariantClear(&v); + if(FAILED(hres)) + return hres; - return S_OK; + return stack_push_string(ctx, ret); +} + +/* ECMA-262 3rd Edition 11.4.3 */ +static HRESULT interp_typeof(exec_ctx_t *ctx) +{ + const WCHAR *ret; + VARIANT *v; + HRESULT hres; + + TRACE("\n"); + + v = stack_pop(ctx); + hres = typeof_string(v, &ret); + VariantClear(v); + if(FAILED(hres)) + return hres; + + return stack_push_string(ctx, ret); } /* ECMA-262 3rd Edition 11.4.7 */ diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index b9e644127f3..0c46383b17b 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -91,6 +91,9 @@ typedef struct _func_stack { X(throw, 0, ARG_UINT, 0) \ X(tonum, 1, 0,0) \ X(tree, 1, ARG_EXPR, 0) \ + X(typeof, 1, 0,0) \ + X(typeofid, 1, 0,0) \ + X(typeofident,1, 0,0) \ X(refval, 1, 0,0) \ X(ret, 0, 0,0) \ X(sub, 1, 0,0) \ @@ -567,7 +570,6 @@ HRESULT identifier_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t* HRESULT property_value_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN; HRESULT delete_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN; -HRESULT typeof_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN; HRESULT compiled_expression_eval(script_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*) DECLSPEC_HIDDEN; diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 88676dd91ae..013b7feb549 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -1319,7 +1319,7 @@ static const expression_eval_t expression_eval_table[] = { compiled_expression_eval, compiled_expression_eval, compiled_expression_eval, - typeof_expression_eval, + compiled_expression_eval, compiled_expression_eval, compiled_expression_eval, compiled_expression_eval,