diff --git a/dlls/jscript/Makefile.in b/dlls/jscript/Makefile.in index 96d8c37e86..095659b717 100644 --- a/dlls/jscript/Makefile.in +++ b/dlls/jscript/Makefile.in @@ -3,7 +3,7 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = jscript.dll -IMPORTS = kernel32 +IMPORTS = oleaut32 kernel32 RC_SRCS = rsrc.rc diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index a65e5d893b..827087f610 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -23,6 +23,83 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); +static inline HRESULT stat_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) +{ + return stat->eval(ctx, stat, rt, ret); +} + +HRESULT create_exec_ctx(exec_ctx_t **ret) +{ + exec_ctx_t *ctx; + + ctx = heap_alloc_zero(sizeof(exec_ctx_t)); + if(!ctx) + return E_OUTOFMEMORY; + + *ret = ctx; + return S_OK; +} + +void exec_release(exec_ctx_t *ctx) +{ + if(--ctx->ref) + return; + + heap_free(ctx); +} + +HRESULT exec_source(exec_ctx_t *ctx, parser_ctx_t *parser, source_elements_t *source, jsexcept_t *ei, VARIANT *retv) +{ + script_ctx_t *script = parser->script; + parser_ctx_t *prev_parser; + VARIANT val, tmp; + statement_t *stat; + exec_ctx_t *prev_ctx; + return_type_t rt; + HRESULT hres = S_OK; + + prev_ctx = script->exec_ctx; + script->exec_ctx = ctx; + + prev_parser = ctx->parser; + ctx->parser = parser; + + V_VT(&val) = VT_EMPTY; + memset(&rt, 0, sizeof(rt)); + rt.type = RT_NORMAL; + + for(stat = source->statement; stat; stat = stat->next) { + hres = stat_eval(ctx, stat, &rt, &tmp); + if(FAILED(hres)) + break; + + VariantClear(&val); + val = tmp; + if(rt.type != RT_NORMAL) + break; + } + + script->exec_ctx = prev_ctx; + ctx->parser = prev_parser; + + if(rt.type != RT_NORMAL && rt.type != RT_RETURN) { + FIXME("wrong rt %d\n", rt.type); + hres = E_FAIL; + } + + *ei = rt.ei; + if(FAILED(hres)) { + VariantClear(&val); + return hres; + } + + if(retv) + *retv = val; + else + VariantClear(&val); + return S_OK; +} + HRESULT block_statement_eval(exec_ctx_t *ctx, statement_t *stat, return_type_t *rt, VARIANT *ret) { FIXME("\n"); diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 1fad3dd6c7..6e91178b43 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -32,6 +32,8 @@ typedef struct _parser_ctx_t { jsheap_t tmp_heap; jsheap_t heap; + + struct _parser_ctx_t *next; } parser_ctx_t; HRESULT script_parse(script_ctx_t*,const WCHAR*,parser_ctx_t**); @@ -54,17 +56,20 @@ static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size) return jsheap_alloc(&ctx->tmp_heap, size); } -typedef struct { - enum{ - RT_NORMAL, - RT_RETURN, - RT_BREAK - } type; -} return_type_t; +struct _exec_ctx_t { + LONG ref; -typedef struct _exec_ctx_t { parser_ctx_t *parser; -} exec_ctx_t; +}; + +static inline void exec_addref(exec_ctx_t *ctx) +{ + ctx->ref++; +} + +void exec_release(exec_ctx_t*); +HRESULT create_exec_ctx(exec_ctx_t**); +HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,jsexcept_t*,VARIANT*); typedef struct _statement_t statement_t; typedef struct _expression_t expression_t; @@ -88,6 +93,16 @@ typedef struct _variable_declaration_t { struct _variable_declaration_t *next; } variable_declaration_t; +typedef struct { + enum{ + RT_NORMAL, + RT_RETURN, + RT_BREAK, + RT_CONTINUE + } type; + jsexcept_t ei; +} return_type_t; + typedef HRESULT (*statement_eval_t)(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); struct _statement_t { @@ -201,7 +216,6 @@ HRESULT throw_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); HRESULT try_statement_eval(exec_ctx_t*,statement_t*,return_type_t*,VARIANT*); typedef struct exprval_t exprval_t; -typedef struct jsexcept_t jsexcept_t; typedef HRESULT (*expression_eval_t)(exec_ctx_t*,expression_t*,DWORD,jsexcept_t*,exprval_t*); diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 27cf0714df..adfd73cb73 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -38,6 +38,9 @@ typedef struct { LONG thread_id; IActiveScriptSite *site; + + parser_ctx_t *queue_head; + parser_ctx_t *queue_tail; } JScript; #define ACTSCRIPT(x) ((IActiveScript*) &(x)->lpIActiveScriptVtbl) @@ -63,6 +66,56 @@ static void change_state(JScript *This, SCRIPTSTATE state) IActiveScriptSite_OnStateChange(This->site, state); } +static inline BOOL is_started(script_ctx_t *ctx) +{ + return ctx->state == SCRIPTSTATE_STARTED + || ctx->state == SCRIPTSTATE_CONNECTED + || ctx->state == SCRIPTSTATE_DISCONNECTED; +} + +static HRESULT exec_global_code(JScript *This, parser_ctx_t *parser_ctx) +{ + exec_ctx_t *exec_ctx; + jsexcept_t jsexcept; + VARIANT var; + HRESULT hres; + + hres = create_exec_ctx(&exec_ctx); + if(FAILED(hres)) + return hres; + + IActiveScriptSite_OnEnterScript(This->site); + + memset(&jsexcept, 0, sizeof(jsexcept)); + hres = exec_source(exec_ctx, parser_ctx, parser_ctx->source, &jsexcept, &var); + VariantClear(&jsexcept.var); + exec_release(exec_ctx); + if(SUCCEEDED(hres)) + VariantClear(&var); + + IActiveScriptSite_OnLeaveScript(This->site); + + return hres; +} + +static void clear_script_queue(JScript *This) +{ + parser_ctx_t *iter, *iter2; + + if(!This->queue_head) + return; + + iter = This->queue_head; + while(iter) { + iter2 = iter->next; + iter->next = NULL; + parser_release(iter); + iter = iter2; + } + + This->queue_head = This->queue_tail = NULL; +} + #define ACTSCRIPT_THIS(iface) DEFINE_THIS(JScript, IActiveScript, iface) static HRESULT WINAPI JScript_QueryInterface(IActiveScript *iface, REFIID riid, void **ppv) @@ -216,6 +269,8 @@ static HRESULT WINAPI JScript_Close(IActiveScript *iface) if(This->thread_id != GetCurrentThreadId()) return E_UNEXPECTED; + clear_script_queue(This); + if(This->ctx) { change_state(This, SCRIPTSTATE_CLOSED); @@ -398,16 +453,29 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, parser_ctx_t *parser_ctx; HRESULT hres; - FIXME("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode), + TRACE("(%p)->(%s %s %p %s %x %u %x %p %p)\n", This, debugstr_w(pstrCode), debugstr_w(pstrItemName), punkContext, debugstr_w(pstrDelimiter), dwSourceContextCookie, ulStartingLine, dwFlags, pvarResult, pexcepinfo); + if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) + return E_UNEXPECTED; + hres = script_parse(This->ctx, pstrCode, &parser_ctx); if(FAILED(hres)) return hres; + if(!is_started(This->ctx)) { + if(This->queue_tail) + This->queue_tail = This->queue_tail->next = parser_ctx; + else + This->queue_head = This->queue_tail = parser_ctx; + return S_OK; + } + + hres = exec_global_code(This, parser_ctx); parser_release(parser_ctx); - return E_NOTIMPL; + + return hres; } #undef ASPARSE_THIS diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 1f55604aa1..0fff0e89ba 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -32,6 +32,12 @@ #include "wine/list.h" typedef struct _script_ctx_t script_ctx_t; +typedef struct _exec_ctx_t exec_ctx_t; + +typedef struct { + EXCEPINFO ei; + VARIANT var; +} jsexcept_t; typedef struct DispatchEx { const IDispatchExVtbl *lpIDispatchExVtbl; @@ -49,6 +55,7 @@ struct _script_ctx_t { LONG ref; SCRIPTSTATE state; + exec_ctx_t *exec_ctx; LCID lcid; DispatchEx *script_disp;