[JSCRIPT] Sync with Wine Staging 1.9.11. CORE-11368

svn path=/trunk/; revision=71557
This commit is contained in:
Amine Khaldi 2016-06-05 19:25:30 +00:00
parent 8fff423976
commit 6f2fa805b0
14 changed files with 599 additions and 534 deletions

View file

@ -550,12 +550,20 @@ static HRESULT compile_new_expression(compiler_ctx_t *ctx, call_expression_t *ex
arg_cnt++; arg_cnt++;
} }
return push_instr_uint(ctx, OP_new, arg_cnt); hres = push_instr_uint(ctx, OP_new, arg_cnt);
if(FAILED(hres))
return hres;
hres = push_instr_uint(ctx, OP_pop, arg_cnt+1);
if(FAILED(hres))
return hres;
return push_instr(ctx, OP_push_ret) ? S_OK : E_OUTOFMEMORY;
} }
static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret) static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *expr, BOOL emit_ret)
{ {
unsigned arg_cnt = 0; unsigned arg_cnt = 0, extra_args;
argument_t *arg; argument_t *arg;
unsigned instr; unsigned instr;
jsop_t op; jsop_t op;
@ -563,9 +571,11 @@ static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *e
if(is_memberid_expr(expr->expression->type)) { if(is_memberid_expr(expr->expression->type)) {
op = OP_call_member; op = OP_call_member;
extra_args = 2;
hres = compile_memberid_expression(ctx, expr->expression, 0); hres = compile_memberid_expression(ctx, expr->expression, 0);
}else { }else {
op = OP_call; op = OP_call;
extra_args = 1;
hres = compile_expression(ctx, expr->expression, TRUE); hres = compile_expression(ctx, expr->expression, TRUE);
} }
@ -585,7 +595,12 @@ static HRESULT compile_call_expression(compiler_ctx_t *ctx, call_expression_t *e
instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt; instr_ptr(ctx, instr)->u.arg[0].uint = arg_cnt;
instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret; instr_ptr(ctx, instr)->u.arg[1].lng = emit_ret;
return S_OK;
hres = push_instr_uint(ctx, OP_pop, arg_cnt + extra_args);
if(FAILED(hres))
return hres;
return !emit_ret || push_instr(ctx, OP_push_ret) ? S_OK : E_OUTOFMEMORY;
} }
static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr) static HRESULT compile_delete_expression(compiler_ctx_t *ctx, unary_expression_t *expr)
@ -849,17 +864,11 @@ static HRESULT compile_object_literal(compiler_ctx_t *ctx, property_value_expres
return S_OK; return S_OK;
} }
static HRESULT compile_function_expression(compiler_ctx_t *ctx, function_expression_t *expr) 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); 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;
/* FIXME: not exactly right */
if(expr->identifier && !expr->event_target) {
ctx->func->func_cnt++;
return push_instr_bstr(ctx, OP_ident, expr->identifier);
}
return push_instr_uint(ctx, OP_func, ctx->func->func_cnt++);
} }
static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret) static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL emit_ret)
@ -944,8 +953,7 @@ static HRESULT compile_expression(compiler_ctx_t *ctx, expression_t *expr, BOOL
hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2); hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_eq2);
break; break;
case EXPR_FUNC: case EXPR_FUNC:
hres = compile_function_expression(ctx, (function_expression_t*)expr); return compile_function_expression(ctx, (function_expression_t*)expr, emit_ret);
break;
case EXPR_GREATER: case EXPR_GREATER:
hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt); hres = compile_binary_expression(ctx, (binary_expression_t*)expr, OP_gt);
break; break;
@ -1471,7 +1479,7 @@ static HRESULT compile_return_statement(compiler_ctx_t *ctx, expression_statemen
if(FAILED(hres)) if(FAILED(hres))
return hres; return hres;
return push_instr(ctx, OP_ret) ? S_OK : E_OUTOFMEMORY; return push_instr_uint(ctx, OP_ret, !stat->expr);
} }
/* ECMA-262 3rd Edition 12.10 */ /* ECMA-262 3rd Edition 12.10 */
@ -1849,8 +1857,9 @@ static HRESULT compile_function(compiler_ctx_t *ctx, source_elements_t *source,
resolve_labels(ctx, off); resolve_labels(ctx, off);
if(!push_instr(ctx, OP_ret)) hres = push_instr_uint(ctx, OP_ret, !from_eval);
return E_OUTOFMEMORY; if(FAILED(hres))
return hres;
if(TRACE_ON(jscript_disas)) if(TRACE_ON(jscript_disas))
dump_code(ctx, off); dump_code(ctx, off);

View file

@ -2163,6 +2163,28 @@ static inline HRESULT date_parse(jsstr_t *input_str, double *ret) {
year = tmp; year = tmp;
} }
} }
else if(parse[i]=='+' || parse[i]=='-') {
/* Timezone offset */
BOOL positive = TRUE;
if(set_offset && set_hour_adjust) break;
set_offset = TRUE;
set_hour_adjust = FALSE;
if(parse[i] == '-') positive = FALSE;
i++;
while(isspaceW(parse[i])) i++;
if(parse[i]<'0' || parse[i]>'9') break;
offset = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
if(offset<24) offset *= 60;
else offset = (offset/100)*60 + offset%100;
if(positive) offset = -offset;
}
else { else {
if(parse[i]<'A' || parse[i]>'Z') break; if(parse[i]<'A' || parse[i]>'Z') break;
else if(parse[i]=='B' && (parse[i+1]=='C' || else if(parse[i]=='B' && (parse[i+1]=='C' ||
@ -2219,27 +2241,11 @@ static inline HRESULT date_parse(jsstr_t *input_str, double *ret) {
else if((parse[i]=='U' && parse[i+1]=='T' && parse[i+2]=='C') else if((parse[i]=='U' && parse[i+1]=='T' && parse[i+2]=='C')
|| (parse[i]=='G' && parse[i+1]=='M' && parse[i+2]=='T')) { || (parse[i]=='G' && parse[i+1]=='M' && parse[i+2]=='T')) {
/* Timezone */ /* Timezone */
BOOL positive = TRUE;
if(set_offset) break; if(set_offset) break;
set_offset = TRUE; set_offset = TRUE;
set_hour_adjust = FALSE; set_hour_adjust = FALSE;
i += 3; i += 3;
while(isspaceW(parse[i])) i++;
if(parse[i] == '-') positive = FALSE;
else if(parse[i] != '+') continue;
i++;
while(isspaceW(parse[i])) i++;
if(parse[i]<'0' || parse[i]>'9') break;
offset = atoiW(&parse[i]);
while(parse[i]>='0' && parse[i]<='9') i++;
if(offset<24) offset *= 60;
else offset = (offset/100)*60 + offset%100;
if(positive) offset = -offset;
} }
else { else {
/* Month or garbage */ /* Month or garbage */

View file

@ -87,7 +87,7 @@ static BOOL decode_dword(const WCHAR *p, DWORD *ret)
DWORD i; DWORD i;
for(i=0; i<6; i++) { for(i=0; i<6; i++) {
if(p[i] > sizeof(digits)/sizeof(*digits) || digits[p[i]] == 0xff) if(p[i] >= sizeof(digits)/sizeof(*digits) || digits[p[i]] == 0xff)
return FALSE; return FALSE;
} }
if(p[6] != '=' || p[7] != '=') if(p[6] != '=' || p[7] != '=')

View file

@ -370,6 +370,8 @@ static HRESULT invoke_prop_func(jsdisp_t *This, IDispatch *jsthis, dispex_prop_t
if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) { if(prop->name || This->builtin_info->class != JSCLASS_FUNCTION) {
vdisp_t vthis; vdisp_t vthis;
if(This->builtin_info->class != JSCLASS_FUNCTION && prop->u.p->invoke != JSGlobal_eval)
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
if(jsthis) if(jsthis)
set_disp(&vthis, jsthis); set_disp(&vthis, jsthis);
else else
@ -1053,7 +1055,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig
{ {
HRESULT hres; HRESULT hres;
assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT))); assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK)));
if(is_class(jsfunc, JSCLASS_FUNCTION)) { if(is_class(jsfunc, JSCLASS_FUNCTION)) {
hres = Function_invoke(jsfunc, jsthis, flags, argc, argv, r); hres = Function_invoke(jsfunc, jsthis, flags, argc, argv, r);
@ -1066,6 +1068,7 @@ HRESULT jsdisp_call_value(jsdisp_t *jsfunc, IDispatch *jsthis, WORD flags, unsig
} }
set_disp(&vdisp, jsthis); set_disp(&vdisp, jsthis);
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
hres = jsfunc->builtin_info->value_prop.invoke(jsfunc->ctx, &vdisp, flags, argc, argv, r); hres = jsfunc->builtin_info->value_prop.invoke(jsfunc->ctx, &vdisp, flags, argc, argv, r);
vdisp_release(&vdisp); vdisp_release(&vdisp);
} }
@ -1116,6 +1119,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
return hres; return hres;
} }
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
if(ret && argc) if(ret && argc)
flags |= DISPATCH_PROPERTYGET; flags |= DISPATCH_PROPERTYGET;
@ -1180,6 +1184,7 @@ HRESULT disp_call(script_ctx_t *ctx, IDispatch *disp, DISPID id, WORD flags, uns
hres = variant_to_jsval(&retv, ret); hres = variant_to_jsval(&retv, ret);
VariantClear(&retv); VariantClear(&retv);
} }
return hres; return hres;
} }
@ -1193,7 +1198,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
unsigned i; unsigned i;
HRESULT hres; HRESULT hres;
assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT))); assert(!(flags & ~(DISPATCH_METHOD|DISPATCH_CONSTRUCT|DISPATCH_JSCRIPT_INTERNAL_MASK)));
jsdisp = iface_to_jsdisp((IUnknown*)disp); jsdisp = iface_to_jsdisp((IUnknown*)disp);
if(jsdisp) { if(jsdisp) {
@ -1202,6 +1207,7 @@ HRESULT disp_call_value(script_ctx_t *ctx, IDispatch *disp, IDispatch *jsthis, W
return hres; return hres;
} }
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
if(r && argc && flags == DISPATCH_METHOD) if(r && argc && flags == DISPATCH_METHOD)
flags |= DISPATCH_PROPERTYGET; flags |= DISPATCH_PROPERTYGET;

File diff suppressed because it is too large Load diff

View file

@ -72,6 +72,7 @@
X(postinc, 1, ARG_INT, 0) \ X(postinc, 1, ARG_INT, 0) \
X(preinc, 1, ARG_INT, 0) \ X(preinc, 1, ARG_INT, 0) \
X(push_except,1, ARG_ADDR, ARG_BSTR) \ X(push_except,1, ARG_ADDR, ARG_BSTR) \
X(push_ret, 1, 0,0) \
X(push_scope, 1, 0,0) \ X(push_scope, 1, 0,0) \
X(regexp, 1, ARG_STR, ARG_UINT) \ X(regexp, 1, ARG_STR, ARG_UINT) \
X(rshift, 1, 0,0) \ X(rshift, 1, 0,0) \
@ -169,9 +170,10 @@ typedef struct _bytecode_t {
HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,BOOL,BOOL,bytecode_t**) DECLSPEC_HIDDEN; HRESULT compile_script(script_ctx_t*,const WCHAR*,const WCHAR*,const WCHAR*,BOOL,BOOL,bytecode_t**) DECLSPEC_HIDDEN;
void release_bytecode(bytecode_t*) DECLSPEC_HIDDEN; void release_bytecode(bytecode_t*) DECLSPEC_HIDDEN;
static inline void bytecode_addref(bytecode_t *code) static inline bytecode_t *bytecode_addref(bytecode_t *code)
{ {
code->ref++; code->ref++;
return code;
} }
typedef struct _scope_chain_t { typedef struct _scope_chain_t {
@ -184,41 +186,41 @@ typedef struct _scope_chain_t {
HRESULT scope_push(scope_chain_t*,jsdisp_t*,IDispatch*,scope_chain_t**) DECLSPEC_HIDDEN; HRESULT scope_push(scope_chain_t*,jsdisp_t*,IDispatch*,scope_chain_t**) DECLSPEC_HIDDEN;
void scope_release(scope_chain_t*) DECLSPEC_HIDDEN; void scope_release(scope_chain_t*) DECLSPEC_HIDDEN;
static inline void scope_addref(scope_chain_t *scope) static inline scope_chain_t *scope_addref(scope_chain_t *scope)
{ {
scope->ref++; scope->ref++;
return scope;
} }
typedef struct _except_frame_t except_frame_t; typedef struct _except_frame_t except_frame_t;
struct _parser_ctx_t; struct _parser_ctx_t;
struct _exec_ctx_t { typedef struct _call_frame_t {
LONG ref; unsigned ip;
struct _parser_ctx_t *parser;
bytecode_t *code;
script_ctx_t *script;
scope_chain_t *scope_chain;
jsdisp_t *var_disp;
IDispatch *this_obj;
function_code_t *func_code;
BOOL is_global;
jsval_t *stack;
unsigned stack_size;
unsigned top;
except_frame_t *except_frame; except_frame_t *except_frame;
unsigned stack_base;
scope_chain_t *scope;
scope_chain_t *base_scope;
jsval_t ret; jsval_t ret;
unsigned ip; IDispatch *this_obj;
}; jsdisp_t *function_instance;
jsdisp_t *variable_obj;
jsdisp_t *arguments_obj;
DWORD flags;
static inline void exec_addref(exec_ctx_t *ctx) bytecode_t *bytecode;
{ function_code_t *function;
ctx->ref++;
} struct _call_frame_t *prev_frame;
} call_frame_t;
#define EXEC_GLOBAL 0x0001
#define EXEC_CONSTRUCTOR 0x0002
#define EXEC_RETURN_TO_INTERP 0x0004
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;
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,jsval_t*) DECLSPEC_HIDDEN;
HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN; HRESULT create_source_function(script_ctx_t*,bytecode_t*,function_code_t*,scope_chain_t*,jsdisp_t**) DECLSPEC_HIDDEN;

View file

@ -27,7 +27,6 @@ typedef struct {
bytecode_t *code; bytecode_t *code;
function_code_t *func_code; function_code_t *func_code;
DWORD length; DWORD length;
jsdisp_t *arguments;
} FunctionInstance; } FunctionInstance;
typedef struct { typedef struct {
@ -196,10 +195,9 @@ static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, un
} }
static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv, static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, unsigned argc, jsval_t *argv,
jsval_t *r) BOOL is_constructor, BOOL caller_execs_source, jsval_t *r)
{ {
jsdisp_t *var_disp, *arg_disp; jsdisp_t *var_disp, *arg_disp;
exec_ctx_t *exec_ctx;
scope_chain_t *scope; scope_chain_t *scope;
HRESULT hres; HRESULT hres;
@ -232,57 +230,23 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope); hres = scope_push(function->scope_chain, var_disp, to_disp(var_disp), &scope);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
hres = create_exec_ctx(ctx, this_obj, var_disp, scope, FALSE, &exec_ctx); 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); scope_release(scope);
if(SUCCEEDED(hres)) {
jsdisp_t *prev_args;
prev_args = function->arguments;
function->arguments = arg_disp;
hres = exec_source(exec_ctx, function->code, function->func_code, FALSE, r);
function->arguments = prev_args;
exec_release(exec_ctx);
}
} }
/* 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(var_disp, argumentsW, jsval_undefined());
jsdisp_release(arg_disp); jsdisp_release(arg_disp);
jsdisp_release(var_disp); jsdisp_release(var_disp);
return hres; return hres;
} }
static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, unsigned argc, jsval_t *argv,
jsval_t *r)
{
jsdisp_t *this_obj;
jsval_t var;
HRESULT hres;
hres = create_object(ctx, &function->dispex, &this_obj);
if(FAILED(hres))
return hres;
hres = invoke_source(ctx, function, to_disp(this_obj), argc, argv, &var);
if(FAILED(hres)) {
jsdisp_release(this_obj);
return hres;
}
if(is_object_instance(var)) {
jsdisp_release(this_obj);
*r = var;
}else {
jsval_release(var);
*r = jsval_obj(this_obj);
}
return S_OK;
}
static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags, static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags,
unsigned argc, jsval_t *argv, jsval_t *r) unsigned argc, jsval_t *argv, jsval_t *r)
{ {
@ -303,12 +267,12 @@ static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function,
} }
static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj,
unsigned argc, jsval_t *argv, jsval_t *r) unsigned argc, jsval_t *argv, BOOL caller_execs_source, jsval_t *r)
{ {
if(function->value_proc) if(function->value_proc)
return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, argc, argv, r); return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, argc, argv, r);
return invoke_source(ctx, function, this_obj, argc, argv, r); return invoke_source(ctx, function, this_obj, argc, argv, FALSE, caller_execs_source, r);
} }
static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret) static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret)
@ -343,6 +307,7 @@ static HRESULT function_to_string(FunctionInstance *function, jsstr_t **ret)
HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r) HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsigned argc, jsval_t *argv, jsval_t *r)
{ {
const BOOL caller_execs_source = (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0;
FunctionInstance *function; FunctionInstance *function;
TRACE("func %p this %p\n", func_this, jsthis); TRACE("func %p this %p\n", func_this, jsthis);
@ -350,14 +315,25 @@ HRESULT Function_invoke(jsdisp_t *func_this, IDispatch *jsthis, WORD flags, unsi
assert(is_class(func_this, JSCLASS_FUNCTION)); assert(is_class(func_this, JSCLASS_FUNCTION));
function = (FunctionInstance*)func_this; function = (FunctionInstance*)func_this;
flags &= ~DISPATCH_JSCRIPT_INTERNAL_MASK;
if(function->value_proc) if(function->value_proc)
return invoke_value_proc(function->dispex.ctx, function, jsthis, flags, argc, argv, r); return invoke_value_proc(function->dispex.ctx, function, jsthis, flags, argc, argv, r);
if(flags == DISPATCH_CONSTRUCT) if(flags == DISPATCH_CONSTRUCT) {
return invoke_constructor(function->dispex.ctx, function, argc, argv, r); jsdisp_t *this_obj;
HRESULT hres;
hres = create_object(function->dispex.ctx, &function->dispex, &this_obj);
if(FAILED(hres))
return hres;
hres = invoke_source(function->dispex.ctx, function, to_disp(this_obj), argc, argv, TRUE, caller_execs_source, r);
jsdisp_release(this_obj);
return hres;
}
assert(flags == DISPATCH_METHOD); assert(flags == DISPATCH_METHOD);
return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, r); return invoke_source(function->dispex.ctx, function, jsthis, argc, argv, FALSE, caller_execs_source, r);
} }
static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
@ -476,7 +452,7 @@ static HRESULT Function_apply(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, un
} }
if(SUCCEEDED(hres)) if(SUCCEEDED(hres))
hres = call_function(ctx, function, this_obj, cnt, args, r); hres = call_function(ctx, function, this_obj, cnt, args, (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0, r);
if(this_obj) if(this_obj)
IDispatch_Release(this_obj); IDispatch_Release(this_obj);
@ -509,7 +485,7 @@ static HRESULT Function_call(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
cnt = argc-1; cnt = argc-1;
} }
hres = call_function(ctx, function, this_obj, cnt, argv+1, r); hres = call_function(ctx, function, this_obj, cnt, argv+1, (flags & DISPATCH_JSCRIPT_CALLEREXECSSOURCE) != 0, r);
if(this_obj) if(this_obj)
IDispatch_Release(this_obj); IDispatch_Release(this_obj);
@ -552,10 +528,18 @@ HRESULT Function_get_value(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) static HRESULT Function_get_arguments(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
{ {
FunctionInstance *function = function_from_jsdisp(jsthis); FunctionInstance *function = function_from_jsdisp(jsthis);
call_frame_t *frame;
TRACE("\n"); TRACE("\n");
*r = function->arguments ? jsval_obj(jsdisp_addref(function->arguments)) : jsval_null(); for(frame = ctx->call_ctx; frame; frame = frame->prev_frame) {
if(frame->function_instance == &function->dispex) {
*r = jsval_obj(jsdisp_addref(frame->arguments_obj));
return S_OK;
}
}
*r = jsval_null();
return S_OK; return S_OK;
} }

View file

@ -175,9 +175,11 @@ static HRESULT JSGlobal_escape(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, u
} }
/* ECMA-262 3rd Edition 15.1.2.1 */ /* ECMA-262 3rd Edition 15.1.2.1 */
static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv, HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
jsval_t *r) jsval_t *r)
{ {
call_frame_t *frame;
DWORD exec_flags = 0;
bytecode_t *code; bytecode_t *code;
const WCHAR *src; const WCHAR *src;
HRESULT hres; HRESULT hres;
@ -196,7 +198,7 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
return S_OK; return S_OK;
} }
if(!ctx->exec_ctx) { if(!(frame = ctx->call_ctx)) {
FIXME("No active exec_ctx\n"); FIXME("No active exec_ctx\n");
return E_UNEXPECTED; return E_UNEXPECTED;
} }
@ -212,7 +214,12 @@ static HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, uns
return throw_syntax_error(ctx, hres, NULL); return throw_syntax_error(ctx, hres, NULL);
} }
hres = exec_source(ctx->exec_ctx, code, &code->global_code, TRUE, r); if(frame->flags & EXEC_GLOBAL)
exec_flags |= EXEC_GLOBAL;
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);
release_bytecode(code); release_bytecode(code);
return hres; return hres;
} }

View file

@ -66,6 +66,8 @@ void script_release(script_ctx_t *ctx)
heap_pool_free(&ctx->tmp_heap); heap_pool_free(&ctx->tmp_heap);
if(ctx->last_match) if(ctx->last_match)
jsstr_release(ctx->last_match); jsstr_release(ctx->last_match);
assert(!ctx->stack_top);
heap_free(ctx->stack);
ctx->jscaller->ctx = NULL; ctx->jscaller->ctx = NULL;
IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface); IServiceProvider_Release(&ctx->jscaller->IServiceProvider_iface);
@ -92,18 +94,12 @@ static inline BOOL is_started(script_ctx_t *ctx)
static HRESULT exec_global_code(JScript *This, bytecode_t *code) static HRESULT exec_global_code(JScript *This, bytecode_t *code)
{ {
exec_ctx_t *exec_ctx;
HRESULT hres; HRESULT hres;
hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx);
if(FAILED(hres))
return hres;
IActiveScriptSite_OnEnterScript(This->site); IActiveScriptSite_OnEnterScript(This->site);
clear_ei(This->ctx); clear_ei(This->ctx);
hres = exec_source(exec_ctx, code, &code->global_code, FALSE, NULL); hres = exec_source(This->ctx, EXEC_GLOBAL, code, &code->global_code, NULL, NULL, NULL, This->ctx->global, NULL, NULL);
exec_release(exec_ctx);
IActiveScriptSite_OnLeaveScript(This->site); IActiveScriptSite_OnLeaveScript(This->site);
return hres; return hres;
@ -764,26 +760,19 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface,
return hres; return hres;
if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { if(dwFlags & SCRIPTTEXT_ISEXPRESSION) {
exec_ctx_t *exec_ctx; jsval_t r;
hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, TRUE, &exec_ctx); 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);
if(SUCCEEDED(hres)) { if(SUCCEEDED(hres)) {
jsval_t r; if(pvarResult)
hres = jsval_to_variant(r, pvarResult);
IActiveScriptSite_OnEnterScript(This->site); jsval_release(r);
clear_ei(This->ctx);
hres = exec_source(exec_ctx, code, &code->global_code, TRUE, &r);
if(SUCCEEDED(hres)) {
if(pvarResult)
hres = jsval_to_variant(r, pvarResult);
jsval_release(r);
}
exec_release(exec_ctx);
IActiveScriptSite_OnLeaveScript(This->site);
} }
IActiveScriptSite_OnLeaveScript(This->site);
return hres; return hres;
} }

View file

@ -50,7 +50,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript);
typedef struct _jsval_t jsval_t; typedef struct _jsval_t jsval_t;
typedef struct _jsstr_t jsstr_t; typedef struct _jsstr_t jsstr_t;
typedef struct _script_ctx_t script_ctx_t; typedef struct _script_ctx_t script_ctx_t;
typedef struct _exec_ctx_t exec_ctx_t;
typedef struct _dispex_prop_t dispex_prop_t; typedef struct _dispex_prop_t dispex_prop_t;
typedef struct { typedef struct {
@ -116,6 +115,14 @@ extern HINSTANCE jscript_hinstance DECLSPEC_HIDDEN;
#define PROPF_CONST 0x0800 #define PROPF_CONST 0x0800
#define PROPF_DONTDELETE 0x1000 #define PROPF_DONTDELETE 0x1000
/*
* This is our internal dispatch flag informing calee that it's called directly from interpreter.
* If calee is executed as interpreted function, we may let already running interpreter to take
* of execution.
*/
#define DISPATCH_JSCRIPT_CALLEREXECSSOURCE 0x8000
#define DISPATCH_JSCRIPT_INTERNAL_MASK DISPATCH_JSCRIPT_CALLEREXECSSOURCE
/* NOTE: Keep in sync with names in Object.toString implementation */ /* NOTE: Keep in sync with names in Object.toString implementation */
typedef enum { typedef enum {
JSCLASS_NONE, JSCLASS_NONE,
@ -399,7 +406,7 @@ struct _script_ctx_t {
SCRIPTSTATE state; SCRIPTSTATE state;
IActiveScript *active_script; IActiveScript *active_script;
exec_ctx_t *exec_ctx; struct _call_frame_t *call_ctx;
named_item_t *named_items; named_item_t *named_items;
IActiveScriptSite *site; IActiveScriptSite *site;
IInternetHostSecurityManager *secmgr; IInternetHostSecurityManager *secmgr;
@ -414,6 +421,10 @@ struct _script_ctx_t {
IDispatch *host_global; IDispatch *host_global;
jsval_t *stack;
unsigned stack_size;
unsigned stack_top;
jsstr_t *last_match; jsstr_t *last_match;
match_result_t match_parens[9]; match_result_t match_parens[9];
DWORD last_match_index; DWORD last_match_index;
@ -478,6 +489,8 @@ HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*) DECLSPEC_
BOOL bool_obj_value(jsdisp_t*) DECLSPEC_HIDDEN; BOOL bool_obj_value(jsdisp_t*) DECLSPEC_HIDDEN;
unsigned array_get_length(jsdisp_t*) DECLSPEC_HIDDEN; unsigned array_get_length(jsdisp_t*) DECLSPEC_HIDDEN;
HRESULT JSGlobal_eval(script_ctx_t*,vdisp_t*,WORD,unsigned,jsval_t*,jsval_t*) DECLSPEC_HIDDEN;
static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class) static inline BOOL is_class(jsdisp_t *jsdisp, jsclass_t class)
{ {
return jsdisp->builtin_info->class == class; return jsdisp->builtin_info->class == class;

View file

@ -257,8 +257,10 @@ static HRESULT RegExp_set_source(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t va
static HRESULT RegExp_get_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) static HRESULT RegExp_get_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
{ {
FIXME("\n"); TRACE("\n");
return E_NOTIMPL;
*r = jsval_bool(!!(regexp_from_jsdisp(jsthis)->jsregexp->flags & REG_GLOB));
return S_OK;
} }
static HRESULT RegExp_set_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) static HRESULT RegExp_set_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value)
@ -269,8 +271,10 @@ static HRESULT RegExp_set_global(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t va
static HRESULT RegExp_get_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) static HRESULT RegExp_get_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
{ {
FIXME("\n"); TRACE("\n");
return E_NOTIMPL;
*r = jsval_bool(!!(regexp_from_jsdisp(jsthis)->jsregexp->flags & REG_FOLD));
return S_OK;
} }
static HRESULT RegExp_set_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) static HRESULT RegExp_set_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value)
@ -281,8 +285,10 @@ static HRESULT RegExp_set_ignoreCase(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_
static HRESULT RegExp_get_multiline(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r) static HRESULT RegExp_get_multiline(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
{ {
FIXME("\n"); TRACE("\n");
return E_NOTIMPL;
*r = jsval_bool(!!(regexp_from_jsdisp(jsthis)->jsregexp->flags & REG_MULTILINE));
return S_OK;
} }
static HRESULT RegExp_set_multiline(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value) static HRESULT RegExp_set_multiline(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t value)

View file

@ -589,7 +589,7 @@ static int next_token(parser_ctx_t *ctx, void *lval)
return '}'; return '}';
case '.': case '.':
if(++ctx->ptr < ctx->end && isdigitW(*ctx->ptr)) { if(ctx->ptr+1 < ctx->end && isdigitW(ctx->ptr[1])) {
double n; double n;
HRESULT hres; HRESULT hres;
hres = parse_decimal(&ctx->ptr, ctx->end, &n); hres = parse_decimal(&ctx->ptr, ctx->end, &n);
@ -600,6 +600,7 @@ static int next_token(parser_ctx_t *ctx, void *lval)
*(literal_t**)lval = new_double_literal(ctx, n); *(literal_t**)lval = new_double_literal(ctx, n);
return tNumericLiteral; return tNumericLiteral;
} }
ctx->ptr++;
return '.'; return '.';
case '<': case '<':

View file

@ -18,8 +18,6 @@
#include "jscript.h" #include "jscript.h"
#define UINT32_MAX 0xffffffff
typedef struct { typedef struct {
jsdisp_t dispex; jsdisp_t dispex;
jsstr_t *str; jsstr_t *str;

View file

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