[JSCRIPT] Sync with Wine Staging 1.9.16. CORE-11866

svn path=/trunk/; revision=72346
This commit is contained in:
Amine Khaldi 2016-08-19 09:36:35 +00:00
parent 6873f2c1ae
commit 4dd5cd6d92
16 changed files with 1221 additions and 409 deletions

View file

@ -178,7 +178,7 @@ static HRESULT concat_obj(jsdisp_t *array, IDispatch *obj, DWORD *len)
jsdisp_t *jsobj;
HRESULT hres;
jsobj = iface_to_jsdisp((IUnknown*)obj);
jsobj = iface_to_jsdisp(obj);
if(jsobj) {
if(is_class(jsobj, JSCLASS_ARRAY)) {
hres = concat_array(array, (ArrayInstance*)jsobj, len);
@ -688,7 +688,7 @@ static HRESULT Array_sort(script_ctx_t *ctx, vdisp_t *vthis, WORD flags, unsigne
return E_FAIL;
}
cmp_func = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
cmp_func = iface_to_jsdisp(get_object(argv[0]));
if(!cmp_func || !is_class(cmp_func, JSCLASS_FUNCTION)) {
WARN("cmp_func is not a function\n");
if(cmp_func)

View file

@ -46,12 +46,13 @@ typedef struct {
unsigned labels_size;
unsigned labels_cnt;
local_ref_t *locals_buf;
unsigned locals_buf_size;
unsigned locals_cnt;
statement_ctx_t *stat_ctx;
function_code_t *func;
variable_declaration_t *var_head;
variable_declaration_t *var_tail;
function_expression_t *func_head;
function_expression_t *func_tail;
} compiler_ctx_t;
@ -399,6 +400,40 @@ static inline BOOL is_memberid_expr(expression_type_t type)
return type == EXPR_IDENT || type == EXPR_MEMBER || type == EXPR_ARRAY;
}
static BOOL bind_local(compiler_ctx_t *ctx, const WCHAR *identifier, int *ret_ref)
{
statement_ctx_t *iter;
local_ref_t *ref;
for(iter = ctx->stat_ctx; iter; iter = iter->next) {
if(iter->using_scope)
return FALSE;
}
ref = lookup_local(ctx->func, identifier);
if(!ref)
return FALSE;
*ret_ref = ref->ref;
return TRUE;
}
static HRESULT emit_identifier_ref(compiler_ctx_t *ctx, const WCHAR *identifier, unsigned flags)
{
int local_ref;
if(bind_local(ctx, identifier, &local_ref))
return push_instr_int(ctx, OP_local_ref, local_ref);
return push_instr_bstr_uint(ctx, OP_identid, identifier, flags);
}
static HRESULT emit_identifier(compiler_ctx_t *ctx, const WCHAR *identifier)
{
int local_ref;
if(bind_local(ctx, identifier, &local_ref))
return push_instr_int(ctx, OP_local, local_ref);
return push_instr_bstr(ctx, OP_ident, identifier);
}
static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *expr, unsigned flags)
{
HRESULT hres = S_OK;
@ -407,7 +442,7 @@ static HRESULT compile_memberid_expression(compiler_ctx_t *ctx, expression_t *ex
case EXPR_IDENT: {
identifier_expression_t *ident_expr = (identifier_expression_t*)expr;
hres = push_instr_bstr_uint(ctx, OP_identid, ident_expr->identifier, flags);
hres = emit_identifier_ref(ctx, ident_expr->identifier, flags);
break;
}
case EXPR_ARRAY: {
@ -866,9 +901,7 @@ static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expres
static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr, BOOL emit_ret)
{
unsigned func_id = ctx->func->func_cnt++;
ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
return emit_ret ? push_instr_uint(ctx, OP_func, func_id) : S_OK;
return emit_ret ? push_instr_uint(ctx, OP_func, expr->func_id) : S_OK;
}
static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret)
@ -961,7 +994,7 @@ static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL
hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gteq);
break;
case EXPR_IDENT:
hres = push_instr_bstr(ctx, OP_ident, ((identifier_expression_t*)expr)->identifier);
hres = emit_identifier(ctx, ((identifier_expression_t*)expr)->identifier);
break;
case EXPR_IN:
hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_in);
@ -1084,25 +1117,22 @@ static HRESULT compile_variable_list(compiler_ctx_t *ctx, variable_declaration_t
assert(list != NULL);
if(ctx->var_tail)
ctx->var_tail->global_next = list;
else
ctx->var_head = list;
for(iter = list; iter; iter = iter->next) {
ctx->func->var_cnt++;
iter->global_next = iter->next;
if(!iter->next)
ctx->var_tail = iter;
if(!iter->expr)
continue;
hres = emit_identifier_ref(ctx, iter->identifier, 0);
if(FAILED(hres))
return hres;
hres = compile_expression(ctx, iter->expr, TRUE);
if(FAILED(hres))
return hres;
hres = push_instr_bstr(ctx, OP_var_set, iter->identifier);
if(!push_instr(ctx, OP_assign))
return E_OUTOFMEMORY;
hres = push_instr_uint(ctx, OP_pop, 1);
if(FAILED(hres))
return hres;
}
@ -1300,7 +1330,7 @@ static HRESULT compile_forin_statement(compiler_ctx_t *ctx, forin_statement_t *s
return hres;
if(stat->variable) {
hres = push_instr_bstr_uint(ctx, OP_identid, stat->variable->identifier, fdexNameEnsure);
hres = emit_identifier_ref(ctx, stat->variable->identifier, fdexNameEnsure);
if(FAILED(hres))
return hres;
}else if(is_memberid_expr(stat->expr->type)) {
@ -1774,6 +1804,393 @@ static HRESULT compile_statement(compiler_ctx_t *ctx, statement_ctx_t *stat_ctx,
return hres;
}
static int local_cmp(const void *key, const void *ref)
{
return strcmpW((const WCHAR*)key, ((const local_ref_t*)ref)->name);
}
static inline local_ref_t *find_local(compiler_ctx_t *ctx, const WCHAR *name)
{
return bsearch(name, ctx->locals_buf, ctx->locals_cnt, sizeof(*ctx->locals_buf), local_cmp);
}
static BOOL alloc_local(compiler_ctx_t *ctx, BSTR name, int ref)
{
unsigned i;
if(!ctx->locals_buf_size) {
ctx->locals_buf = heap_alloc(4 * sizeof(*ctx->locals_buf));
if(!ctx->locals_buf)
return FALSE;
ctx->locals_buf_size = 4;
}else if(ctx->locals_buf_size == ctx->locals_cnt) {
local_ref_t *new_buf = heap_realloc(ctx->locals_buf, ctx->locals_buf_size * 2 * sizeof(*ctx->locals_buf));
if(!new_buf)
return FALSE;
ctx->locals_buf = new_buf;
ctx->locals_buf_size *= 2;
}
for(i = 0; i < ctx->locals_cnt; i++) {
if(strcmpW(ctx->locals_buf[i].name, name) > 0) {
memmove(ctx->locals_buf + i+1, ctx->locals_buf + i, (ctx->locals_cnt - i) * sizeof(*ctx->locals_buf));
break;
}
}
ctx->locals_buf[i].name = name;
ctx->locals_buf[i].ref = ref;
ctx->locals_cnt++;
return TRUE;
}
static BOOL alloc_variable(compiler_ctx_t *ctx, const WCHAR *name)
{
BSTR ident;
if(find_local(ctx, name))
return TRUE;
ident = compiler_alloc_bstr(ctx, name);
if(!ident)
return FALSE;
return alloc_local(ctx, ident, ctx->func->var_cnt++);
}
static BOOL visit_function_expression(compiler_ctx_t *ctx, function_expression_t *expr)
{
expr->func_id = ctx->func->func_cnt++;
ctx->func_tail = ctx->func_tail ? (ctx->func_tail->next = expr) : (ctx->func_head = expr);
return !expr->identifier || expr->event_target || alloc_variable(ctx, expr->identifier);
}
static HRESULT visit_expression(compiler_ctx_t *ctx, expression_t *expr)
{
HRESULT hres = S_OK;
switch(expr->type) {
case EXPR_ADD:
case EXPR_AND:
case EXPR_ARRAY:
case EXPR_ASSIGN:
case EXPR_ASSIGNADD:
case EXPR_ASSIGNAND:
case EXPR_ASSIGNSUB:
case EXPR_ASSIGNMUL:
case EXPR_ASSIGNDIV:
case EXPR_ASSIGNMOD:
case EXPR_ASSIGNOR:
case EXPR_ASSIGNLSHIFT:
case EXPR_ASSIGNRSHIFT:
case EXPR_ASSIGNRRSHIFT:
case EXPR_ASSIGNXOR:
case EXPR_BAND:
case EXPR_BOR:
case EXPR_COMMA:
case EXPR_DIV:
case EXPR_EQ:
case EXPR_EQEQ:
case EXPR_GREATER:
case EXPR_GREATEREQ:
case EXPR_IN:
case EXPR_INSTANCEOF:
case EXPR_LESS:
case EXPR_LESSEQ:
case EXPR_LSHIFT:
case EXPR_MOD:
case EXPR_MUL:
case EXPR_NOTEQ:
case EXPR_NOTEQEQ:
case EXPR_OR:
case EXPR_RSHIFT:
case EXPR_RRSHIFT:
case EXPR_SUB:
case EXPR_BXOR: {
binary_expression_t *binary_expr = (binary_expression_t*)expr;
hres = visit_expression(ctx, binary_expr->expression1);
if(FAILED(hres))
return hres;
hres = visit_expression(ctx, binary_expr->expression2);
break;
}
case EXPR_BITNEG:
case EXPR_DELETE:
case EXPR_LOGNEG:
case EXPR_MINUS:
case EXPR_PLUS:
case EXPR_POSTDEC:
case EXPR_POSTINC:
case EXPR_PREDEC:
case EXPR_PREINC:
case EXPR_TYPEOF:
case EXPR_VOID:
hres = visit_expression(ctx, ((unary_expression_t*)expr)->expression);
break;
case EXPR_IDENT:
case EXPR_LITERAL:
case EXPR_THIS:
break;
case EXPR_ARRAYLIT: {
array_literal_expression_t *array_expr = (array_literal_expression_t*)expr;
array_element_t *iter;
for(iter = array_expr->element_list; iter; iter = iter->next) {
hres = visit_expression(ctx, iter->expr);
if(FAILED(hres))
return hres;
}
break;
}
case EXPR_CALL:
case EXPR_NEW: {
call_expression_t *call_expr = (call_expression_t*)expr;
argument_t *arg;
hres = visit_expression(ctx, call_expr->expression);
if(FAILED(hres))
return hres;
for(arg = call_expr->argument_list; arg; arg = arg->next) {
hres = visit_expression(ctx, arg->expr);
if(FAILED(hres))
return hres;
}
break;
}
case EXPR_COND: {
conditional_expression_t *cond_expr = (conditional_expression_t*)expr;
hres = visit_expression(ctx, cond_expr->expression);
if(FAILED(hres))
return hres;
hres = visit_expression(ctx, cond_expr->true_expression);
if(FAILED(hres))
return hres;
hres = visit_expression(ctx, cond_expr->false_expression);
break;
}
case EXPR_FUNC:
visit_function_expression(ctx, (function_expression_t*)expr);
break;
case EXPR_MEMBER:
hres = visit_expression(ctx, ((member_expression_t*)expr)->expression);
break;
case EXPR_PROPVAL: {
prop_val_t *iter;
for(iter = ((property_value_expression_t*)expr)->property_list; iter; iter = iter->next) {
hres = visit_expression(ctx, iter->value);
if(FAILED(hres))
return hres;
}
break;
}
DEFAULT_UNREACHABLE;
}
return hres;
}
static HRESULT visit_variable_list(compiler_ctx_t *ctx, variable_declaration_t *list)
{
variable_declaration_t *iter;
HRESULT hres;
for(iter = list; iter; iter = iter->next) {
if(!alloc_variable(ctx, iter->identifier))
return E_OUTOFMEMORY;
if(iter->expr) {
hres = visit_expression(ctx, iter->expr);
if(FAILED(hres))
return hres;
}
}
return S_OK;
}
static HRESULT visit_statement(compiler_ctx_t*,statement_t*);
static HRESULT visit_block_statement(compiler_ctx_t *ctx, statement_t *iter)
{
HRESULT hres;
while(iter) {
hres = visit_statement(ctx, iter);
if(FAILED(hres))
return hres;
iter = iter->next;
}
return S_OK;
}
static HRESULT visit_statement(compiler_ctx_t *ctx, statement_t *stat)
{
HRESULT hres = S_OK;
switch(stat->type) {
case STAT_BLOCK:
hres = visit_block_statement(ctx, ((block_statement_t*)stat)->stat_list);
break;
case STAT_BREAK:
case STAT_CONTINUE:
case STAT_EMPTY:
break;
case STAT_EXPR:
case STAT_RETURN:
case STAT_THROW: {
expression_statement_t *expr_stat = (expression_statement_t*)stat;
if(expr_stat->expr)
hres = visit_expression(ctx, expr_stat->expr);
break;
}
case STAT_FOR: {
for_statement_t *for_stat = (for_statement_t*)stat;
if(for_stat->variable_list)
hres = visit_variable_list(ctx, for_stat->variable_list);
else if(for_stat->begin_expr)
hres = visit_expression(ctx, for_stat->begin_expr);
if(FAILED(hres))
break;
if(for_stat->expr) {
hres = visit_expression(ctx, for_stat->expr);
if(FAILED(hres))
break;
}
hres = visit_statement(ctx, for_stat->statement);
if(FAILED(hres))
break;
if(for_stat->end_expr)
hres = visit_expression(ctx, for_stat->end_expr);
break;
}
case STAT_FORIN: {
forin_statement_t *forin_stat = (forin_statement_t*)stat;
if(forin_stat->variable) {
hres = visit_variable_list(ctx, forin_stat->variable);
if(FAILED(hres))
break;
}
hres = visit_expression(ctx, forin_stat->in_expr);
if(FAILED(hres))
return hres;
if(forin_stat->expr) {
hres = visit_expression(ctx, forin_stat->expr);
if(FAILED(hres))
return hres;
}
hres = visit_statement(ctx, forin_stat->statement);
break;
}
case STAT_IF: {
if_statement_t *if_stat = (if_statement_t*)stat;
hres = visit_expression(ctx, if_stat->expr);
if(FAILED(hres))
return hres;
hres = visit_statement(ctx, if_stat->if_stat);
if(FAILED(hres))
return hres;
if(if_stat->else_stat)
hres = visit_statement(ctx, if_stat->else_stat);
break;
}
case STAT_LABEL:
hres = visit_statement(ctx, ((labelled_statement_t*)stat)->statement);
break;
case STAT_SWITCH: {
switch_statement_t *switch_stat = (switch_statement_t*)stat;
statement_t *stat_iter;
case_clausule_t *iter;
hres = visit_expression(ctx, switch_stat->expr);
if(FAILED(hres))
return hres;
for(iter = switch_stat->case_list; iter; iter = iter->next) {
if(!iter->expr)
continue;
hres = visit_expression(ctx, iter->expr);
if(FAILED(hres))
return hres;
}
for(iter = switch_stat->case_list; iter; iter = iter->next) {
while(iter->next && iter->next->stat == iter->stat)
iter = iter->next;
for(stat_iter = iter->stat; stat_iter && (!iter->next || iter->next->stat != stat_iter);
stat_iter = stat_iter->next) {
hres = visit_statement(ctx, stat_iter);
if(FAILED(hres))
return hres;
}
}
break;
}
case STAT_TRY: {
try_statement_t *try_stat = (try_statement_t*)stat;
hres = visit_statement(ctx, try_stat->try_statement);
if(FAILED(hres))
return hres;
if(try_stat->catch_block) {
hres = visit_statement(ctx, try_stat->catch_block->statement);
if(FAILED(hres))
return hres;
}
if(try_stat->finally_statement)
hres = visit_statement(ctx, try_stat->finally_statement);
break;
}
case STAT_VAR:
hres = visit_variable_list(ctx, ((var_statement_t*)stat)->variable_list);
break;
case STAT_WHILE: {
while_statement_t *while_stat = (while_statement_t*)stat;
hres = visit_expression(ctx, while_stat->expr);
if(FAILED(hres))
return hres;
hres = visit_statement(ctx, while_stat->statement);
break;
}
case STAT_WITH: {
with_statement_t *with_stat = (with_statement_t*)stat;
hres = visit_expression(ctx, with_stat->expr);
if(FAILED(hres))
return hres;
hres = visit_statement(ctx, with_stat->statement);
break;
}
DEFAULT_UNREACHABLE;
}
return hres;
}
static void resolve_labels(compiler_ctx_t *ctx, unsigned off)
{
instr_t *instr;
@ -1838,35 +2255,20 @@ static HRESULT init_code(compiler_ctx_t *compiler, const WCHAR *source)
static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source, function_expression_t *func_expr,
BOOL from_eval, function_code_t *func)
{
variable_declaration_t *var_iter;
function_expression_t *iter;
unsigned off, i;
unsigned off, i, j;
HRESULT hres;
TRACE("\n");
ctx->var_head = ctx->var_tail = NULL;
ctx->func_head = ctx->func_tail = NULL;
ctx->from_eval = from_eval;
off = ctx->code_off;
ctx->func = func;
hres = compile_block_statement(ctx, source->statement);
if(FAILED(hres))
return hres;
resolve_labels(ctx, off);
hres = push_instr_uint(ctx, OP_ret, !from_eval);
if(FAILED(hres))
return hres;
if(TRACE_ON(jscript_disas))
dump_code(ctx, off);
func->instr_off = off;
ctx->locals_cnt = 0;
if(func_expr) {
parameter_t *param_iter;
if(func_expr->identifier) {
func->name = compiler_alloc_bstr(ctx, func_expr->identifier);
if(!func->name)
@ -1878,10 +2280,6 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
if(!func->event_target)
return E_OUTOFMEMORY;
}
}
if(func_expr) {
parameter_t *param_iter;
func->source = func_expr->src_str;
func->source_len = func_expr->src_len;
@ -1900,27 +2298,69 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
}
}
for(i = 0; i < func->param_cnt; i++) {
if(!find_local(ctx, func->params[i]) && !alloc_local(ctx, func->params[i], -i-1))
return E_OUTOFMEMORY;
}
hres = visit_block_statement(ctx, source->statement);
if(FAILED(hres))
return hres;
func->locals = compiler_alloc(ctx->code, ctx->locals_cnt * sizeof(*func->locals));
if(!func->locals)
return E_OUTOFMEMORY;
func->locals_cnt = ctx->locals_cnt;
memcpy(func->locals, ctx->locals_buf, func->locals_cnt * sizeof(*func->locals));
func->variables = compiler_alloc(ctx->code, func->var_cnt * sizeof(*func->variables));
if(!func->variables)
return E_OUTOFMEMORY;
for(var_iter = ctx->var_head, i=0; var_iter; var_iter = var_iter->global_next, i++) {
func->variables[i] = compiler_alloc_bstr(ctx, var_iter->identifier);
if(!func->variables[i])
return E_OUTOFMEMORY;
for(i = 0, j = 0; i < func->locals_cnt; i++) {
if(func->locals[i].ref < 0)
continue; /* skip arguments */
func->variables[func->locals[i].ref].name = func->locals[i].name;
func->variables[func->locals[i].ref].func_id = -1;
j++;
}
assert(i == func->var_cnt);
assert(j == func->var_cnt);
func->funcs = compiler_alloc(ctx->code, func->func_cnt * sizeof(*func->funcs));
if(!func->funcs)
return E_OUTOFMEMORY;
memset(func->funcs, 0, func->func_cnt * sizeof(*func->funcs));
off = ctx->code_off;
hres = compile_block_statement(ctx, source->statement);
if(FAILED(hres))
return hres;
resolve_labels(ctx, off);
hres = push_instr_uint(ctx, OP_ret, !from_eval);
if(FAILED(hres))
return hres;
if(TRACE_ON(jscript_disas))
dump_code(ctx, off);
func->instr_off = off;
for(iter = ctx->func_head, i=0; iter; iter = iter->next, i++) {
hres = compile_function(ctx, iter->source_elements, iter, FALSE, func->funcs+i);
if(FAILED(hres))
return hres;
TRACE("[%d] func %s\n", i, debugstr_w(func->funcs[i].name));
if(func->funcs[i].name && !func->funcs[i].event_target) {
local_ref_t *local_ref = lookup_local(func, func->funcs[i].name);
func->funcs[i].local_ref = local_ref->ref;
TRACE("found ref %s %d for %s\n", debugstr_w(local_ref->name), local_ref->ref, debugstr_w(func->funcs[i].name));
if(local_ref->ref >= 0)
func->variables[local_ref->ref].func_id = i;
}
}
assert(i == func->func_cnt);
@ -2030,6 +2470,7 @@ HRESULT compile_script(script_ctx_t *ctx, const WCHAR *code, const WCHAR *args,
hres = compile_function(&compiler, compiler.parser->source, NULL, from_eval, &compiler.code->global_code);
parser_release(compiler.parser);
heap_free(compiler.locals_buf);
if(FAILED(hres)) {
release_bytecode(compiler.code);
return hres;

View file

@ -18,13 +18,6 @@
#include "jscript.h"
/*
* This IID is used to get jsdisp_t objecto from interface.
* We might consider using private interface instead.
*/
static const IID IID_IDispatchJS =
{0x719c3050,0xf9d3,0x11cf,{0xa4,0x93,0x00,0x40,0x05,0x23,0xa8,0xa6}};
#define FDEX_VERSION_MASK 0xf0000000
#define GOLDEN_RATIO 0x9E3779B9U
@ -491,10 +484,8 @@ static HRESULT prop_put(jsdisp_t *This, dispex_prop_t *prop, jsval_t val, IServi
TRACE("%s = %s\n", debugstr_w(prop->name), debugstr_jsval(val));
hres = jsval_copy(val, &prop->u.val);
if(FAILED(hres)) {
prop->u.val = jsval_undefined();
if(FAILED(hres))
return hres;
}
if(This->builtin_info->on_put)
This->builtin_info->on_put(This, prop->name);
@ -558,11 +549,6 @@ static HRESULT WINAPI DispatchEx_QueryInterface(IDispatchEx *iface, REFIID riid,
}else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
*ppv = &This->IDispatchEx_iface;
}else if(IsEqualGUID(&IID_IDispatchJS, riid)) {
TRACE("(%p)->(IID_IDispatchJS %p)\n", This, ppv);
jsdisp_addref(This);
*ppv = This;
return S_OK;
}else {
WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
*ppv = NULL;
@ -584,6 +570,7 @@ static ULONG WINAPI DispatchEx_Release(IDispatchEx *iface)
{
jsdisp_t *This = impl_from_IDispatchEx(iface);
ULONG ref = --This->ref;
TRACE("(%p) ref=%d\n", This, ref);
if(!ref)
jsdisp_free(This);
return ref;
@ -1007,7 +994,7 @@ HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const built
}
if(is_object_instance(val))
prot = iface_to_jsdisp((IUnknown*)get_object(val));
prot = iface_to_jsdisp(get_object(val));
jsval_release(val);
}
@ -1018,16 +1005,11 @@ HRESULT init_dispex_from_constr(jsdisp_t *dispex, script_ctx_t *ctx, const built
return hres;
}
jsdisp_t *iface_to_jsdisp(IUnknown *iface)
jsdisp_t *iface_to_jsdisp(IDispatch *iface)
{
jsdisp_t *ret;
HRESULT hres;
hres = IUnknown_QueryInterface(iface, &IID_IDispatchJS, (void**)&ret);
if(FAILED(hres))
return NULL;
return ret;
return iface->lpVtbl == (const IDispatchVtbl*)&DispatchExVtbl
? jsdisp_addref( impl_from_IDispatchEx((IDispatchEx*)iface))
: NULL;
}
HRESULT jsdisp_get_id(jsdisp_t *jsdisp, const WCHAR *name, DWORD flags, DISPID *id)
@ -1107,7 +1089,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
unsigned i;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
jsdisp = iface_to_jsdisp(disp);
if(jsdisp) {
if(flags & DISPATCH_PROPERTYPUT) {
FIXME("disp_call(propput) on builtin object\n");
@ -1200,7 +1182,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK)));
jsdisp = iface_to_jsdisp((IUnknown*)disp);
jsdisp = iface_to_jsdisp(disp);
if(jsdisp) {
hres = jsdisp_call_value(jsdisp, jsthis, flags, argc, argv, r);
jsdisp_release(jsdisp);
@ -1339,7 +1321,7 @@ HRESULT disp_propput(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t val)
jsdisp_t *jsdisp;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
jsdisp = iface_to_jsdisp(disp);
if(jsdisp) {
dispex_prop_t *prop;
@ -1444,7 +1426,7 @@ HRESULT disp_propget(script_ctx_t *ctx, IDispatch *disp, DISPID id, jsval_t *val
VARIANT var;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
jsdisp = iface_to_jsdisp(disp);
if(jsdisp) {
hres = jsdisp_propget(jsdisp, id, val);
jsdisp_release(jsdisp);
@ -1495,7 +1477,7 @@ HRESULT disp_delete(IDispatch *disp, DISPID id, BOOL *ret)
jsdisp_t *jsdisp;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
jsdisp = iface_to_jsdisp(disp);
if(jsdisp) {
dispex_prop_t *prop;
@ -1531,7 +1513,7 @@ HRESULT disp_delete_name(script_ctx_t *ctx, IDispatch *disp, jsstr_t *name, BOOL
BSTR bstr;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
jsdisp = iface_to_jsdisp(disp);
if(jsdisp) {
dispex_prop_t *prop;
const WCHAR *ptr;

File diff suppressed because it is too large Load diff

View file

@ -50,6 +50,8 @@
X(int, 1, ARG_INT, 0) \
X(jmp, 0, ARG_ADDR, 0) \
X(jmp_z, 0, ARG_ADDR, 0) \
X(local, 1, ARG_INT, 0) \
X(local_ref, 1, ARG_INT, ARG_UINT) \
X(lshift, 1, 0,0) \
X(lt, 1, 0,0) \
X(lteq, 1, 0,0) \
@ -91,7 +93,6 @@
X(setret, 1, 0,0) \
X(sub, 1, 0,0) \
X(undefined, 1, 0,0) \
X(var_set, 1, ARG_BSTR, 0) \
X(void, 1, 0,0) \
X(xor, 1, 0,0)
@ -128,8 +129,14 @@ typedef struct {
} u;
} instr_t;
typedef struct {
BSTR name;
int ref;
} local_ref_t;
typedef struct _function_code_t {
BSTR name;
int local_ref;
BSTR event_target;
unsigned instr_off;
@ -140,12 +147,20 @@ typedef struct _function_code_t {
struct _function_code_t *funcs;
unsigned var_cnt;
BSTR *variables;
struct {
BSTR name;
int func_id; /* -1 if not a function */
} *variables;
unsigned param_cnt;
BSTR *params;
unsigned locals_cnt;
local_ref_t *locals;
} function_code_t;
local_ref_t *lookup_local(const function_code_t*,const WCHAR*) DECLSPEC_HIDDEN;
typedef struct _bytecode_t {
LONG ref;
@ -180,6 +195,7 @@ typedef struct _scope_chain_t {
LONG ref;
jsdisp_t *jsobj;
IDispatch *obj;
struct _call_frame_t *frame;
struct _scope_chain_t *next;
} scope_chain_t;
@ -210,6 +226,12 @@ typedef struct _call_frame_t {
jsdisp_t *arguments_obj;
DWORD flags;
unsigned argc;
unsigned pop_locals;
unsigned arguments_off;
unsigned variables_off;
unsigned pop_variables;
bytecode_t *bytecode;
function_code_t *function;
@ -219,8 +241,11 @@ typedef struct _call_frame_t {
#define EXEC_GLOBAL 0x0001
#define EXEC_CONSTRUCTOR 0x0002
#define EXEC_RETURN_TO_INTERP 0x0004
#define EXEC_EVAL 0x0008
HRESULT exec_source(script_ctx_t*,DWORD,bytecode_t*,function_code_t*,scope_chain_t*,IDispatch*,
jsdisp_t*,jsdisp_t*,jsdisp_t*,jsval_t*) DECLSPEC_HIDDEN;
jsdisp_t*,jsdisp_t*,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN;
HRESULT setup_arguments_object(script_ctx_t*,call_frame_t*) DECLSPEC_HIDDEN;
void detach_arguments_object(jsdisp_t*) DECLSPEC_HIDDEN;

View file

@ -32,7 +32,9 @@ typedef struct {
typedef struct {
jsdisp_t jsdisp;
FunctionInstance *function;
jsdisp_t *var_obj;
jsval_t *buf;
call_frame_t *frame;
unsigned argc;
} ArgumentsInstance;
static inline FunctionInstance *function_from_jsdisp(jsdisp_t *jsdisp)
@ -50,6 +52,11 @@ static inline FunctionInstance *function_this(vdisp_t *jsthis)
return is_vclass(jsthis, JSCLASS_FUNCTION) ? function_from_vdisp(jsthis) : NULL;
}
static inline ArgumentsInstance *arguments_from_jsdisp(jsdisp_t *jsdisp)
{
return CONTAINING_RECORD(jsdisp, ArgumentsInstance, jsdisp);
}
static const WCHAR prototypeW[] = {'p','r','o','t','o','t', 'y', 'p','e',0};
static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
@ -58,21 +65,6 @@ static const WCHAR applyW[] = {'a','p','p','l','y',0};
static const WCHAR callW[] = {'c','a','l','l',0};
static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
static HRESULT init_parameters(jsdisp_t *var_disp, FunctionInstance *function, unsigned argc, jsval_t *argv)
{
DWORD i=0;
HRESULT hres;
for(i=0; i < function->func_code->param_cnt; i++) {
hres = jsdisp_propput_name(var_disp, function->func_code->params[i],
i < argc ? argv[i] : jsval_undefined());
if(FAILED(hres))
return hres;
}
return S_OK;
}
static HRESULT Arguments_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r)
{
@ -84,35 +76,69 @@ static void Arguments_destructor(jsdisp_t *jsdisp)
{
ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
TRACE("(%p)\n", arguments);
if(arguments->buf) {
unsigned i;
for(i = 0; i < arguments->argc; i++)
jsval_release(arguments->buf[i]);
heap_free(arguments->buf);
}
jsdisp_release(&arguments->function->dispex);
jsdisp_release(arguments->var_obj);
heap_free(arguments);
}
static unsigned Arguments_idx_length(jsdisp_t *jsdisp)
{
ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
return arguments->function->length;
return arguments->argc;
}
static HRESULT Arguments_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *res)
static jsval_t *get_argument_ref(ArgumentsInstance *arguments, unsigned idx)
{
if(arguments->buf)
return arguments->buf + idx;
if(arguments->frame->base_scope->frame || idx >= arguments->frame->function->param_cnt)
return arguments->jsdisp.ctx->stack + arguments->frame->arguments_off + idx;
return NULL;
}
static HRESULT Arguments_idx_get(jsdisp_t *jsdisp, unsigned idx, jsval_t *r)
{
ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
jsval_t *ref;
TRACE("%p[%u]\n", arguments, idx);
if((ref = get_argument_ref(arguments, idx)))
return jsval_copy(*ref, r);
/* FIXME: Accessing by name won't work for duplicated argument names */
return jsdisp_propget_name(arguments->var_obj, arguments->function->func_code->params[idx], res);
return jsdisp_propget_name(arguments->frame->base_scope->jsobj, arguments->function->func_code->params[idx], r);
}
static HRESULT Arguments_idx_put(jsdisp_t *jsdisp, unsigned idx, jsval_t val)
{
ArgumentsInstance *arguments = (ArgumentsInstance*)jsdisp;
jsval_t *ref;
HRESULT hres;
TRACE("%p[%u] = %s\n", arguments, idx, debugstr_jsval(val));
if((ref = get_argument_ref(arguments, idx))) {
jsval_t copy;
hres = jsval_copy(val, &copy);
if(FAILED(hres))
return hres;
jsval_release(*ref);
*ref = copy;
return S_OK;
}
/* FIXME: Accessing by name won't work for duplicated argument names */
return jsdisp_propput_name(arguments->var_obj, arguments->function->func_code->params[idx], val);
return jsdisp_propput_name(arguments->frame->base_scope->jsobj, arguments->function->func_code->params[idx], val);
}
static const builtin_info_t Arguments_info = {
@ -126,11 +152,9 @@ static const builtin_info_t Arguments_info = {
Arguments_idx_put
};
static HRESULT create_arguments(script_ctx_t *ctx, FunctionInstance *calee, jsdisp_t *var_obj,
unsigned argc, jsval_t *argv, jsdisp_t **ret)
HRESULT setup_arguments_object(script_ctx_t *ctx, call_frame_t *frame)
{
ArgumentsInstance *args;
unsigned i;
HRESULT hres;
static const WCHAR caleeW[] = {'c','a','l','l','e','e',0};
@ -145,60 +169,64 @@ static HRESULT create_arguments(script_ctx_t *ctx, FunctionInstance *calee, jsdi
return hres;
}
jsdisp_addref(&calee->dispex);
args->function = calee;
args->var_obj = jsdisp_addref(var_obj);
args->function = function_from_jsdisp(jsdisp_addref(frame->function_instance));
args->argc = frame->argc;
args->frame = frame;
/* Store unnamed arguments directly in arguments object */
for(i = calee->length; i < argc; i++) {
WCHAR buf[12];
static const WCHAR formatW[] = {'%','d',0};
sprintfW(buf, formatW, i);
hres = jsdisp_propput_dontenum(&args->jsdisp, buf, argv[i]);
if(FAILED(hres))
break;
}
if(SUCCEEDED(hres)) {
hres = jsdisp_propput_dontenum(&args->jsdisp, lengthW, jsval_number(argc));
if(SUCCEEDED(hres))
hres = jsdisp_propput_dontenum(&args->jsdisp, caleeW, jsval_disp(to_disp(&calee->dispex)));
}
hres = jsdisp_propput_dontenum(&args->jsdisp, lengthW, jsval_number(args->argc));
if(SUCCEEDED(hres))
hres = jsdisp_propput_dontenum(&args->jsdisp, caleeW, jsval_disp(to_disp(&args->function->dispex)));
if(SUCCEEDED(hres))
hres = jsdisp_propput(frame->base_scope->jsobj, argumentsW, PROPF_DONTDELETE, jsval_obj(&args->jsdisp));
if(FAILED(hres)) {
jsdisp_release(&args->jsdisp);
return hres;
}
*ret = &args->jsdisp;
frame->arguments_obj = &args->jsdisp;
return S_OK;
}
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, unsigned argc, jsval_t *argv, jsdisp_t **ret)
void detach_arguments_object(jsdisp_t *args_disp)
{
jsdisp_t *var_disp;
ArgumentsInstance *arguments = arguments_from_jsdisp(args_disp);
call_frame_t *frame = arguments->frame;
const BOOL on_stack = frame->base_scope->frame == frame;
HRESULT hres;
hres = create_dispex(ctx, NULL, NULL, &var_disp);
if(FAILED(hres))
return hres;
/* Reset arguments value to cut the reference cycle. Note that since all activation contexts have
* their own arguments property, it's impossible to use prototype's one during name lookup */
jsdisp_propput_name(frame->base_scope->jsobj, argumentsW, jsval_undefined());
arguments->frame = NULL;
hres = init_parameters(var_disp, function, argc, argv);
if(FAILED(hres)) {
jsdisp_release(var_disp);
return hres;
/* Don't bother coppying arguments if call frame holds the last reference. */
if(arguments->jsdisp.ref > 1) {
arguments->buf = heap_alloc(arguments->argc * sizeof(*arguments->buf));
if(arguments->buf) {
int i;
for(i = 0; i < arguments->argc ; i++) {
if(on_stack || i >= frame->function->param_cnt)
hres = jsval_copy(arguments->jsdisp.ctx->stack[frame->arguments_off + i], arguments->buf+i);
else
hres = jsdisp_propget_name(frame->base_scope->jsobj, frame->function->params[i], arguments->buf+i);
if(FAILED(hres))
arguments->buf[i] = jsval_undefined();
}
}else {
ERR("out of memory\n");
arguments->argc = 0;
}
}
*ret = var_disp;
return S_OK;
jsdisp_release(frame->arguments_obj);
}
static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv,
BOOL is_constructor, BOOL caller_execs_source, jsval_t *r)
{
jsdisp_t *var_disp, *arg_disp;
scope_chain_t *scope;
jsdisp_t *var_disp;
DWORD exec_flags = 0;
HRESULT hres;
if(ctx->state == SCRIPTSTATE_UNINITIALIZED || ctx->state == SCRIPTSTATE_CLOSED) {
@ -211,38 +239,17 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
return E_FAIL;
}
hres = create_var_disp(ctx, function, argc, argv, &var_disp);
hres = create_dispex(ctx, NULL, NULL, &var_disp);
if(FAILED(hres))
return hres;
hres = create_arguments(ctx, function, var_disp, argc, argv, &arg_disp);
if(FAILED(hres)) {
jsdisp_release(var_disp);
return hres;
}
if(caller_execs_source)
exec_flags |= EXEC_RETURN_TO_INTERP;
if(is_constructor)
exec_flags |= EXEC_CONSTRUCTOR;
hres = exec_source(ctx, exec_flags, function->code, function->func_code, function->scope_chain, this_obj,
&function->dispex, var_disp, argc, argv, r);
hres = jsdisp_propput(var_disp, argumentsW, PROPF_DONTDELETE, jsval_obj(arg_disp));
if(FAILED(hres)) {
jsdisp_release(arg_disp);
jsdisp_release(var_disp);
return hres;
}
hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope);
if(SUCCEEDED(hres)) {
DWORD exec_flags = 0;
if(caller_execs_source)
exec_flags |= EXEC_RETURN_TO_INTERP;
if(is_constructor)
exec_flags |= EXEC_CONSTRUCTOR;
hres = exec_source(ctx, exec_flags, function->code, function->func_code, scope, this_obj,
&function->dispex, var_disp, arg_disp, r);
scope_release(scope);
}
jsdisp_release(arg_disp);
jsdisp_release(var_disp);
return hres;
}
@ -419,7 +426,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
TRACE("\n");
if(!(function = function_this(jsthis)))
if(!(function = function_this(jsthis)) && (jsthis->flags & VDISP_JSDISP))
return throw_type_error(ctx, JS_E_FUNCTION_EXPECTED, NULL);
if(argc) {
@ -434,7 +441,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
jsdisp_t *arg_array = NULL;
if(is_object_instance(argv[1])) {
arg_array = iface_to_jsdisp((IUnknown*)get_object(argv[1]));
arg_array = iface_to_jsdisp(get_object(argv[1]));
if(arg_array &&
(!is_class(arg_array, JSCLASS_ARRAY) && !is_class(arg_array, JSCLASS_ARGUMENTS) )) {
jsdisp_release(arg_array);
@ -451,8 +458,20 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
}
}
if(SUCCEEDED(hres))
hres = call_function(ctx, function, this_obj, cnt, args, (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0, r);
if(SUCCEEDED(hres)) {
if(function) {
hres = call_function(ctx, function, this_obj, cnt, args, (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0, r);
}else {
jsval_t res;
hres = disp_call_value(ctx, jsthis->u.disp, this_obj, DISPATCH_METHOD, cnt, args, &res);
if(SUCCEEDED(hres)) {
if(r)
*r = res;
else
jsval_release(res);
}
}
}
if(this_obj)
IDispatch_Release(this_obj);
@ -529,11 +548,17 @@ static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval
{
FunctionInstance *function = function_from_jsdisp(jsthis);
call_frame_t *frame;
HRESULT hres;
TRACE("\n");
for(frame = ctx->call_ctx; frame; frame = frame->prev_frame) {
if(frame->function_instance == &function->dispex) {
if(!frame->arguments_obj) {
hres = setup_arguments_object(ctx, frame);
if(FAILED(hres))
return hres;
}
*r = jsval_obj(jsdisp_addref(frame->arguments_obj));
return S_OK;
}
@ -775,7 +800,7 @@ static HRESULT construct_function(script_ctx_t *ctx, unsigned argc, jsval_t *arg
if(FAILED(hres))
return hres;
if(code->global_code.func_cnt != 1 || code->global_code.var_cnt) {
if(code->global_code.func_cnt != 1 || code->global_code.var_cnt != 1) {
ERR("Invalid parser result!\n");
release_bytecode(code);
return E_UNEXPECTED;

View file

@ -179,7 +179,7 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a
jsval_t *r)
{
call_frame_t *frame;
DWORD exec_flags = 0;
DWORD exec_flags = EXEC_EVAL;
bytecode_t *code;
const WCHAR *src;
HRESULT hres;
@ -219,7 +219,7 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a
if(flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE)
exec_flags |= EXEC_RETURN_TO_INTERP;
hres = exec_source(ctx, exec_flags, code, &code->global_code, frame->scope,
frame->this_obj, NULL, frame->variable_obj, NULL, r);
frame->this_obj, NULL, frame->variable_obj, 0, NULL, r);
release_bytecode(code);
return hres;
}

View file

@ -99,7 +99,7 @@ static HRESULT exec_global_code(JScript *This, bytecode_t *code)
IActiveScriptSite_OnEnterScript(This->site);
clear_ei(This->ctx);
hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, NULL, NULL);
hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, NULL);
IActiveScriptSite_OnLeaveScript(This->site);
return hres;
@ -765,7 +765,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
IActiveScriptSite_OnEnterScript(This->site);
clear_ei(This->ctx);
hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, NULL, &r);
hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, 0, NULL, &r);
if(SUCCEEDED(hres)) {
if(pvarResult)
hres = jsval_to_variant(r, pvarResult);

View file

@ -142,7 +142,7 @@ typedef enum {
JSCLASS_JSON
} jsclass_t;
jsdisp_t *iface_to_jsdisp(IUnknown*) DECLSPEC_HIDDEN;
jsdisp_t *iface_to_jsdisp(IDispatch*) DECLSPEC_HIDDEN;
typedef struct {
union {
@ -184,7 +184,7 @@ static inline void set_disp(vdisp_t *vdisp, IDispatch *disp)
jsdisp_t *jsdisp;
HRESULT hres;
jsdisp = iface_to_jsdisp((IUnknown*)disp);
jsdisp = iface_to_jsdisp(disp);
if(jsdisp) {
vdisp->u.jsdisp = jsdisp;
vdisp->flags = VDISP_JSDISP | VDISP_DISPEX;

View file

@ -412,7 +412,7 @@ static HRESULT maybe_to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *r)
jsdisp_t *obj;
HRESULT hres;
if(!is_object_instance(val) || !get_object(val) || !(obj = iface_to_jsdisp((IUnknown*)get_object(val))))
if(!is_object_instance(val) || !get_object(val) || !(obj = iface_to_jsdisp(get_object(val))))
return jsval_copy(val, r);
if(is_class(obj, JSCLASS_NUMBER)) {
@ -663,7 +663,7 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsval_t val)
jsdisp_t *obj;
DISPID id;
obj = iface_to_jsdisp((IUnknown*)get_object(val));
obj = iface_to_jsdisp(get_object(val));
if(!obj)
return S_FALSE;
@ -721,7 +721,7 @@ static HRESULT stringify(stringify_ctx_t *ctx, jsval_t val)
case JSV_OBJECT: {
jsdisp_t *obj;
obj = iface_to_jsdisp((IUnknown*)get_object(value));
obj = iface_to_jsdisp(get_object(value));
if(!obj) {
hres = S_FALSE;
break;

View file

@ -328,6 +328,7 @@ static HRESULT RegExp_set_lastIndex(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t
TRACE("\n");
jsval_release(regexp->last_index_val);
hres = jsval_copy(value, &regexp->last_index_val);
if(FAILED(hres))
return hres;
@ -697,7 +698,7 @@ HRESULT create_regexp_var(script_ctx_t *ctx, jsval_t src_arg, jsval_t *flags_arg
if(is_object_instance(src_arg)) {
jsdisp_t *obj;
obj = iface_to_jsdisp((IUnknown*)get_object(src_arg));
obj = iface_to_jsdisp(get_object(src_arg));
if(obj) {
if(is_class(obj, JSCLASS_REGEXP)) {
RegExpInstance *regexp = (RegExpInstance*)obj;
@ -948,7 +949,7 @@ static HRESULT RegExpConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
case DISPATCH_METHOD:
if(argc) {
if(is_object_instance(argv[0])) {
jsdisp_t *jsdisp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
jsdisp_t *jsdisp = iface_to_jsdisp(get_object(argv[0]));
if(jsdisp) {
if(is_class(jsdisp, JSCLASS_REGEXP)) {
if(argc > 1 && !is_undefined(argv[1])) {

View file

@ -138,7 +138,7 @@ void heap_pool_clear(heap_pool_t *heap)
if(!heap)
return;
while((tmp = list_next(&heap->custom_blocks, &heap->custom_blocks))) {
while((tmp = list_head(&heap->custom_blocks))) {
list_remove(tmp);
heap_free(tmp);
}
@ -202,13 +202,17 @@ static HRESULT jsval_variant(jsval_t *val, VARIANT *var)
__JSVAL_TYPE(*val) = JSV_VARIANT;
__JSVAL_VAR(*val) = v = heap_alloc(sizeof(VARIANT));
if(!v)
if(!v) {
*val = jsval_undefined();
return E_OUTOFMEMORY;
}
V_VT(v) = VT_EMPTY;
hres = VariantCopy(v, var);
if(FAILED(hres))
if(FAILED(hres)) {
*val = jsval_undefined();
heap_free(v);
}
return hres;
}
@ -382,7 +386,7 @@ HRESULT to_primitive(script_ctx_t *ctx, jsval_t val, jsval_t *ret, hint_t hint)
return S_OK;
}
jsdisp = iface_to_jsdisp((IUnknown*)get_object(val));
jsdisp = iface_to_jsdisp(get_object(val));
if(!jsdisp)
return disp_propget(ctx, get_object(val), DISPID_VALUE, ret);

View file

@ -255,6 +255,9 @@ static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
switch(flags) {
case DISPATCH_METHOD:
case DISPATCH_CONSTRUCT: {
jsdisp_t *obj;
if(argc) {
if(!is_undefined(argv[0]) && !is_null(argv[0]) && (!is_object_instance(argv[0]) || get_object(argv[0]))) {
IDispatch *disp;
@ -270,9 +273,6 @@ static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags
return S_OK;
}
}
/* fall through */
case DISPATCH_CONSTRUCT: {
jsdisp_t *obj;
hres = create_object(ctx, NULL, &obj);
if(FAILED(hres))

View file

@ -296,6 +296,7 @@ typedef struct _function_expression_t {
source_elements_t *source_elements;
const WCHAR *src_str;
DWORD src_len;
unsigned func_id;
struct _function_expression_t *next; /* for compiler */
} function_expression_t;

View file

@ -628,7 +628,7 @@ static HRESULT String_match(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
}
if(is_object_instance(argv[0])) {
regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
regexp = iface_to_jsdisp(get_object(argv[0]));
if(regexp && !is_class(regexp, JSCLASS_REGEXP)) {
jsdisp_release(regexp);
regexp = NULL;
@ -791,7 +791,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
}
if(is_object_instance(argv[0])) {
regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
regexp = iface_to_jsdisp(get_object(argv[0]));
if(regexp && !is_class(regexp, JSCLASS_REGEXP)) {
jsdisp_release(regexp);
regexp = NULL;
@ -808,7 +808,7 @@ static HRESULT String_replace(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
if(argc >= 2) {
if(is_object_instance(argv[1])) {
rep_func = iface_to_jsdisp((IUnknown*)get_object(argv[1]));
rep_func = iface_to_jsdisp(get_object(argv[1]));
if(rep_func && !is_class(rep_func, JSCLASS_FUNCTION)) {
jsdisp_release(rep_func);
rep_func = NULL;
@ -1009,7 +1009,7 @@ static HRESULT String_search(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
}
if(is_object_instance(argv[0])) {
regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
regexp = iface_to_jsdisp(get_object(argv[0]));
if(regexp && !is_class(regexp, JSCLASS_REGEXP)) {
jsdisp_release(regexp);
regexp = NULL;
@ -1153,7 +1153,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi
}
if(is_object_instance(argv[0])) {
regexp = iface_to_jsdisp((IUnknown*)get_object(argv[0]));
regexp = iface_to_jsdisp(get_object(argv[0]));
if(regexp) {
if(!is_class(regexp, JSCLASS_REGEXP)) {
jsdisp_release(regexp);

View file

@ -85,7 +85,7 @@ reactos/dll/win32/inseng # Synced to WineStaging-1.9.11
reactos/dll/win32/iphlpapi # Out of sync
reactos/dll/win32/itircl # Synced to WineStaging-1.9.11
reactos/dll/win32/itss # Synced to WineStaging-1.9.11
reactos/dll/win32/jscript # Synced to WineStaging-1.9.11
reactos/dll/win32/jscript # Synced to WineStaging-1.9.16
reactos/dll/win32/jsproxy # Synced to WineStaging-1.9.11
reactos/dll/win32/loadperf # Synced to WineStaging-1.9.11
reactos/dll/win32/localspl # Synced to WineStaging-1.9.11