jscript: Use bytecode for object literal implementation.
This commit is contained in:
parent
b268e41da6
commit
5e6faaea12
|
@ -619,6 +619,24 @@ static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
|
|||
}
|
||||
}
|
||||
|
||||
static HRESULT literal_as_bstr(compiler_ctx_t *ctx, literal_t *literal, BSTR *str)
|
||||
{
|
||||
switch(literal->type) {
|
||||
case LT_STRING:
|
||||
*str = compiler_alloc_bstr(ctx, literal->u.wstr);
|
||||
break;
|
||||
case LT_INT:
|
||||
*str = int_to_bstr(literal->u.lval);
|
||||
break;
|
||||
case LT_DOUBLE:
|
||||
return double_to_bstr(literal->u.dval, str);
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return *str ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expression_t *expr)
|
||||
{
|
||||
unsigned i, elem_cnt = expr->length;
|
||||
|
@ -646,6 +664,35 @@ static HRESULT compile_array_literal(compiler_ctx_t *ctx, array_literal_expressi
|
|||
return push_instr_uint(ctx, OP_carray, elem_cnt);
|
||||
}
|
||||
|
||||
static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expression_t *expr)
|
||||
{
|
||||
prop_val_t *iter;
|
||||
unsigned instr;
|
||||
BSTR name;
|
||||
HRESULT hres;
|
||||
|
||||
if(push_instr(ctx, OP_new_obj) == -1)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
for(iter = expr->property_list; iter; iter = iter->next) {
|
||||
hres = literal_as_bstr(ctx, iter->name, &name);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = compile_expression(ctx, iter->value);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
instr = push_instr(ctx, OP_obj_prop);
|
||||
if(instr == -1)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
instr_ptr(ctx, instr)->arg1.bstr = name;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
|
||||
{
|
||||
unsigned instr;
|
||||
|
@ -765,6 +812,8 @@ static HRESULT compile_expression_noret(compiler_ctx_t *ctx, expression_t *expr,
|
|||
return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, -1);
|
||||
case EXPR_PREINC:
|
||||
return compile_increment_expression(ctx, (unary_expression_t*)expr, OP_preinc, 1);
|
||||
case EXPR_PROPVAL:
|
||||
return compile_object_literal(ctx, (property_value_expression_t*)expr);
|
||||
case EXPR_RSHIFT:
|
||||
return compile_binary_expression(ctx, (binary_expression_t*)expr, OP_rshift);
|
||||
case EXPR_RRSHIFT:
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "jscript.h"
|
||||
|
||||
#include "wine/unicode.h"
|
||||
|
@ -829,6 +831,12 @@ static IDispatchExVtbl DispatchExVtbl = {
|
|||
DispatchEx_GetNameSpaceParent
|
||||
};
|
||||
|
||||
jsdisp_t *as_jsdisp(IDispatch *disp)
|
||||
{
|
||||
assert(disp->lpVtbl == (IDispatchVtbl*)&DispatchExVtbl);
|
||||
return impl_from_IDispatchEx((IDispatchEx*)disp);
|
||||
}
|
||||
|
||||
HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *builtin_info, jsdisp_t *prototype)
|
||||
{
|
||||
TRACE("%p (%p)\n", dispex, prototype);
|
||||
|
|
|
@ -507,49 +507,6 @@ static HRESULT equal2_values(VARIANT *lval, VARIANT *rval, BOOL *ret)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT literal_to_var(script_ctx_t *ctx, literal_t *literal, VARIANT *v)
|
||||
{
|
||||
switch(literal->type) {
|
||||
case LT_NULL:
|
||||
V_VT(v) = VT_NULL;
|
||||
break;
|
||||
case LT_INT:
|
||||
V_VT(v) = VT_I4;
|
||||
V_I4(v) = literal->u.lval;
|
||||
break;
|
||||
case LT_DOUBLE:
|
||||
V_VT(v) = VT_R8;
|
||||
V_R8(v) = literal->u.dval;
|
||||
break;
|
||||
case LT_STRING: {
|
||||
BSTR str = SysAllocString(literal->u.wstr);
|
||||
if(!str)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
V_VT(v) = VT_BSTR;
|
||||
V_BSTR(v) = str;
|
||||
break;
|
||||
}
|
||||
case LT_BOOL:
|
||||
V_VT(v) = VT_BOOL;
|
||||
V_BOOL(v) = literal->u.bval;
|
||||
break;
|
||||
case LT_REGEXP: {
|
||||
jsdisp_t *regexp;
|
||||
HRESULT hres;
|
||||
|
||||
hres = create_regexp(ctx, literal->u.regexp.str, literal->u.regexp.str_len,
|
||||
literal->u.regexp.flags, ®exp);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
var_set_jsdisp(v, regexp);
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static BOOL lookup_global_members(script_ctx_t *ctx, BSTR identifier, exprval_t *ret)
|
||||
{
|
||||
named_item_t *item;
|
||||
|
@ -1958,55 +1915,40 @@ static HRESULT interp_carray(exec_ctx_t *ctx)
|
|||
}
|
||||
|
||||
/* ECMA-262 3rd Edition 11.1.5 */
|
||||
HRESULT property_value_expression_eval(script_ctx_t *ctx, expression_t *_expr, DWORD flags, jsexcept_t *ei, exprval_t *ret)
|
||||
HRESULT interp_new_obj(exec_ctx_t *ctx)
|
||||
{
|
||||
property_value_expression_t *expr = (property_value_expression_t*)_expr;
|
||||
VARIANT val, tmp;
|
||||
jsdisp_t *obj;
|
||||
prop_val_t *iter;
|
||||
exprval_t exprval;
|
||||
BSTR name;
|
||||
VARIANT v;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
hres = create_object(ctx, NULL, &obj);
|
||||
hres = create_object(ctx->parser->script, NULL, &obj);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
for(iter = expr->property_list; iter; iter = iter->next) {
|
||||
hres = literal_to_var(ctx, iter->name, &tmp);
|
||||
if(FAILED(hres))
|
||||
break;
|
||||
var_set_jsdisp(&v, obj);
|
||||
return stack_push(ctx, &v);
|
||||
}
|
||||
|
||||
hres = to_string(ctx, &tmp, ei, &name);
|
||||
VariantClear(&tmp);
|
||||
if(FAILED(hres))
|
||||
break;
|
||||
/* ECMA-262 3rd Edition 11.1.5 */
|
||||
HRESULT interp_obj_prop(exec_ctx_t *ctx)
|
||||
{
|
||||
const BSTR name = ctx->parser->code->instrs[ctx->ip].arg1.bstr;
|
||||
jsdisp_t *obj;
|
||||
VARIANT *v;
|
||||
HRESULT hres;
|
||||
|
||||
hres = expr_eval(ctx, iter->value, 0, ei, &exprval);
|
||||
if(SUCCEEDED(hres)) {
|
||||
hres = exprval_to_value(ctx, &exprval, ei, &val);
|
||||
exprval_release(&exprval);
|
||||
if(SUCCEEDED(hres)) {
|
||||
hres = jsdisp_propput_name(obj, name, &val, ei, NULL/*FIXME*/);
|
||||
VariantClear(&val);
|
||||
}
|
||||
}
|
||||
TRACE("%s\n", debugstr_w(name));
|
||||
|
||||
SysFreeString(name);
|
||||
if(FAILED(hres))
|
||||
break;
|
||||
}
|
||||
v = stack_pop(ctx);
|
||||
|
||||
if(FAILED(hres)) {
|
||||
jsdisp_release(obj);
|
||||
return hres;
|
||||
}
|
||||
assert(V_VT(stack_top(ctx)) == VT_DISPATCH);
|
||||
obj = as_jsdisp(V_DISPATCH(stack_top(ctx)));
|
||||
|
||||
ret->type = EXPRVAL_VARIANT;
|
||||
var_set_jsdisp(&ret->u.var, obj);
|
||||
return S_OK;
|
||||
hres = jsdisp_propput_name(obj, name, v, &ctx->ei, NULL/*FIXME*/);
|
||||
VariantClear(v);
|
||||
return hres;
|
||||
}
|
||||
|
||||
/* ECMA-262 3rd Edition 11.11 */
|
||||
|
|
|
@ -80,7 +80,9 @@ typedef struct _func_stack {
|
|||
X(neq, 1, 0,0) \
|
||||
X(neq2, 1, 0,0) \
|
||||
X(new, 1, ARG_INT, 0) \
|
||||
X(new_obj, 1, 0,0) \
|
||||
X(null, 1, 0,0) \
|
||||
X(obj_prop, 1, ARG_BSTR, 0) \
|
||||
X(or, 1, 0,0) \
|
||||
X(pop, 1, 0,0) \
|
||||
X(postinc, 1, ARG_INT, 0) \
|
||||
|
@ -568,8 +570,6 @@ typedef struct {
|
|||
prop_val_t *property_list;
|
||||
} property_value_expression_t;
|
||||
|
||||
HRESULT property_value_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;
|
||||
|
||||
HRESULT compile_subscript(parser_ctx_t*,expression_t*,BOOL,unsigned*) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -189,6 +189,8 @@ static inline IDispatch *to_disp(jsdisp_t *jsdisp)
|
|||
return (IDispatch*)&jsdisp->IDispatchEx_iface;
|
||||
}
|
||||
|
||||
jsdisp_t *as_jsdisp(IDispatch*);
|
||||
|
||||
static inline void jsdisp_addref(jsdisp_t *jsdisp)
|
||||
{
|
||||
IDispatchEx_AddRef(&jsdisp->IDispatchEx_iface);
|
||||
|
@ -257,6 +259,9 @@ HRESULT to_uint32(script_ctx_t*,VARIANT*,jsexcept_t*,DWORD*) DECLSPEC_HIDDEN;
|
|||
HRESULT to_string(script_ctx_t*,VARIANT*,jsexcept_t*,BSTR*) DECLSPEC_HIDDEN;
|
||||
HRESULT to_object(script_ctx_t*,VARIANT*,IDispatch**) DECLSPEC_HIDDEN;
|
||||
|
||||
BSTR int_to_bstr(int) DECLSPEC_HIDDEN;
|
||||
HRESULT double_to_bstr(double,BSTR*) DECLSPEC_HIDDEN;
|
||||
|
||||
typedef struct named_item_t {
|
||||
IDispatch *disp;
|
||||
DWORD flags;
|
||||
|
|
|
@ -497,7 +497,7 @@ HRESULT to_uint32(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, DWORD *ret)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static BSTR int_to_bstr(INT i)
|
||||
BSTR int_to_bstr(int i)
|
||||
{
|
||||
WCHAR buf[12], *p;
|
||||
BOOL neg = FALSE;
|
||||
|
@ -527,6 +527,32 @@ static BSTR int_to_bstr(INT i)
|
|||
return SysAllocString(p);
|
||||
}
|
||||
|
||||
HRESULT double_to_bstr(double n, BSTR *str)
|
||||
{
|
||||
const WCHAR NaNW[] = {'N','a','N',0};
|
||||
const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0};
|
||||
|
||||
if(isnan(n)) {
|
||||
*str = SysAllocString(NaNW);
|
||||
}else if(isinf(n)) {
|
||||
*str = SysAllocString(n<0 ? InfinityW : InfinityW+1);
|
||||
}else {
|
||||
VARIANT strv, v;
|
||||
HRESULT hres;
|
||||
|
||||
V_VT(&v) = VT_R8;
|
||||
V_R8(&v) = n;
|
||||
V_VT(&strv) = VT_EMPTY;
|
||||
hres = VariantChangeTypeEx(&strv, &v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
*str = V_BSTR(&strv);
|
||||
}
|
||||
|
||||
return *str ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
/* ECMA-262 3rd Edition 9.8 */
|
||||
HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
|
||||
{
|
||||
|
@ -534,8 +560,6 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
|
|||
const WCHAR nullW[] = {'n','u','l','l',0};
|
||||
const WCHAR trueW[] = {'t','r','u','e',0};
|
||||
const WCHAR falseW[] = {'f','a','l','s','e',0};
|
||||
const WCHAR NaNW[] = {'N','a','N',0};
|
||||
const WCHAR InfinityW[] = {'-','I','n','f','i','n','i','t','y',0};
|
||||
|
||||
switch(V_VT(v)) {
|
||||
case VT_EMPTY:
|
||||
|
@ -548,22 +572,7 @@ HRESULT to_string(script_ctx_t *ctx, VARIANT *v, jsexcept_t *ei, BSTR *str)
|
|||
*str = int_to_bstr(V_I4(v));
|
||||
break;
|
||||
case VT_R8: {
|
||||
if(isnan(V_R8(v)))
|
||||
*str = SysAllocString(NaNW);
|
||||
else if(isinf(V_R8(v)))
|
||||
*str = SysAllocString(V_R8(v)<0 ? InfinityW : InfinityW+1);
|
||||
else {
|
||||
VARIANT strv;
|
||||
HRESULT hres;
|
||||
|
||||
V_VT(&strv) = VT_EMPTY;
|
||||
hres = VariantChangeTypeEx(&strv, v, MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT), 0, VT_BSTR);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
*str = V_BSTR(&strv);
|
||||
return S_OK;
|
||||
}
|
||||
return double_to_bstr(V_R8(v), str);
|
||||
break;
|
||||
}
|
||||
case VT_BSTR:
|
||||
|
|
|
@ -1360,7 +1360,7 @@ static const expression_eval_t expression_eval_table[] = {
|
|||
compiled_expression_eval,
|
||||
compiled_expression_eval,
|
||||
compiled_expression_eval,
|
||||
property_value_expression_eval,
|
||||
compiled_expression_eval,
|
||||
compiled_expression_eval
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue