Each named item should have its own associated script dispatch object. Identifiers are added to this object, but code does look into the global script object as well.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/compile.c | 2 ++ dlls/jscript/dispex.c | 1 + dlls/jscript/engine.c | 33 +++++++++++++++-- dlls/jscript/engine.h | 2 ++ dlls/jscript/global.c | 9 ++++- dlls/jscript/jscript.c | 80 ++++++++++++++++++++++++++++++++++++++++-- dlls/jscript/jscript.h | 2 ++ 7 files changed, 123 insertions(+), 6 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 61db10c..07027c2 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -2250,6 +2250,8 @@ void release_bytecode(bytecode_t *code) for(i=0; i < code->str_cnt; i++) jsstr_release(code->str_pool[i]);
+ if(code->named_item) + release_named_item(code->named_item); heap_free(code->source); heap_pool_free(&code->heap); heap_free(code->bstr_pool); diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index e986de6..a0c8f38 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -1527,6 +1527,7 @@ static HRESULT WINAPI DispatchEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lc }
enter_script(This->ctx, &ei); + ei.script_obj = This;
switch(wFlags) { case DISPATCH_METHOD|DISPATCH_PROPERTYGET: diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index 4e28b63..6b261e7 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -654,6 +654,15 @@ static HRESULT identifier_eval(script_ctx_t *ctx, BSTR identifier, exprval_t *re return S_OK; } } + + if(ctx->call_ctx->bytecode->named_item) { + jsdisp_t *script_obj = ctx->call_ctx->bytecode->named_item->script_obj; + hres = jsdisp_get_id(script_obj, identifier, 0, &id); + if(SUCCEEDED(hres)) { + exprval_set_disp_ref(ret, to_disp(script_obj), id); + return S_OK; + } + } }
hres = jsdisp_get_id(ctx->global, identifier, 0, &id); @@ -1236,13 +1245,17 @@ static HRESULT interp_identifier_ref(script_ctx_t *ctx, BSTR identifier, unsigne return hres;
if(exprval.type == EXPRVAL_INVALID && (flags & fdexNameEnsure)) { + jsdisp_t *script_obj = ctx->global; DISPID id;
- hres = jsdisp_get_id(ctx->global, identifier, fdexNameEnsure, &id); + if(ctx->call_ctx->bytecode->named_item) + script_obj = ctx->call_ctx->bytecode->named_item->script_obj; + + hres = jsdisp_get_id(script_obj, identifier, fdexNameEnsure, &id); if(FAILED(hres)) return hres;
- exprval_set_disp_ref(&exprval, to_disp(ctx->global), id); + exprval_set_disp_ref(&exprval, to_disp(script_obj), id); }
if(exprval.type == EXPRVAL_JSVAL || exprval.type == EXPRVAL_INVALID) { @@ -2972,6 +2985,15 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi unsigned i; HRESULT hres;
+ if(bytecode->named_item) { + if(!bytecode->named_item->script_obj) { + hres = create_named_item_script_obj(ctx, bytecode->named_item); + if(FAILED(hres)) return hres; + } + if(variable_obj == ctx->global) + variable_obj = bytecode->named_item->script_obj; + } + if(!ctx->ei->enter_notified) { ctx->ei->enter_notified = TRUE; IActiveScriptSite_OnEnterScript(ctx->site); @@ -2994,6 +3016,8 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi }
if(flags & (EXEC_GLOBAL | EXEC_EVAL)) { + BOOL lookup_globals = (flags & EXEC_GLOBAL) && !bytecode->named_item; + for(i=0; i < function->var_cnt; i++) { TRACE("[%d] %s %d\n", i, debugstr_w(function->variables[i].name), function->variables[i].func_id); if(function->variables[i].func_id != -1) { @@ -3005,7 +3029,7 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi
hres = jsdisp_propput_name(variable_obj, function->variables[i].name, jsval_obj(func_obj)); jsdisp_release(func_obj); - }else if(!(flags & EXEC_GLOBAL) || !lookup_global_members(ctx, function->variables[i].name, NULL)) { + }else if(!lookup_globals || !lookup_global_members(ctx, function->variables[i].name, NULL)) { DISPID id = 0;
hres = jsdisp_get_id(variable_obj, function->variables[i].name, fdexNameEnsure, &id); @@ -3057,6 +3081,9 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi frame->stack_base = ctx->stack_top; if(this_obj) frame->this_obj = this_obj; + else if(bytecode->named_item) + frame->this_obj = (bytecode->named_item->flags & SCRIPTITEM_CODEONLY) + ? to_disp(bytecode->named_item->script_obj) : bytecode->named_item->disp; else if(ctx->host_global) frame->this_obj = ctx->host_global; else diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index cad46e1..06ef500 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -180,6 +180,7 @@ struct _bytecode_t { heap_pool_t heap;
function_code_t global_code; + named_item_t *named_item;
WCHAR *source; UINT64 source_context; @@ -231,6 +232,7 @@ struct _jsexcept_t { jsstr_t *message; jsstr_t *line;
+ jsdisp_t *script_obj; bytecode_t *code; unsigned loc;
diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index e2758bf..bb53709 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -181,6 +181,7 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a { call_frame_t *frame = ctx->call_ctx; DWORD exec_flags = EXEC_EVAL; + jsdisp_t *context; bytecode_t *code; const WCHAR *src; HRESULT hres; @@ -210,12 +211,18 @@ HRESULT JSGlobal_eval(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned a return hres; }
+ if(frame && frame->bytecode->named_item) { + code->named_item = frame->bytecode->named_item; + code->named_item->ref++; + } + context = frame ? frame->variable_obj : (ctx->ei->script_obj ? ctx->ei->script_obj : ctx->global); + if(!frame || (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 ? frame->scope : NULL, - frame ? frame->this_obj : NULL, NULL, frame ? frame->variable_obj : ctx->global, 0, NULL, r); + frame ? frame->this_obj : NULL, NULL, context, 0, NULL, r); release_bytecode(code); return hres; } diff --git a/dlls/jscript/jscript.c b/dlls/jscript/jscript.c index 8311eef..ebdd5c4 100644 --- a/dlls/jscript/jscript.c +++ b/dlls/jscript/jscript.c @@ -108,6 +108,27 @@ static inline BOOL is_started(script_ctx_t *ctx) || ctx->state == SCRIPTSTATE_DISCONNECTED; }
+HRESULT create_named_item_script_obj(script_ctx_t *ctx, named_item_t *item) +{ + static const builtin_info_t disp_info = { + JSCLASS_GLOBAL, + {NULL, NULL, 0}, + 0, NULL, + NULL, + NULL + }; + + return create_dispex(ctx, &disp_info, NULL, &item->script_obj); +} + +static void release_named_item_script_obj(named_item_t *item) +{ + if(!item->script_obj) return; + + jsdisp_release(item->script_obj); + item->script_obj = NULL; +} + named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *item_name, unsigned flags) { named_item_t *item; @@ -115,6 +136,12 @@ named_item_t *lookup_named_item(script_ctx_t *ctx, const WCHAR *item_name, unsig
for(item = ctx->named_items; item; item = item->next) { if((item->flags & flags) == flags && !wcscmp(item->name, item_name)) { + if(!item->script_obj) { + if(item->flags & SCRIPTITEM_GLOBALMEMBERS) + return item; + hr = create_named_item_script_obj(ctx, item); + if(FAILED(hr)) return NULL; + } if(!item->disp && (flags || !(item->flags & SCRIPTITEM_CODEONLY))) { IUnknown *unk;
@@ -371,6 +398,15 @@ static void clear_persistent_code_list(JScript *This) } }
+static void release_persistent_script_objs(JScript *This) +{ + bytecode_t *iter; + + LIST_FOR_EACH_ENTRY(iter, &This->persistent_code, bytecode_t, entry) + if(iter->named_item) + release_named_item_script_obj(iter->named_item); +} + static void exec_queued_code(JScript *This) { bytecode_t *iter; @@ -408,6 +444,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state) /* FALLTHROUGH */ case SCRIPTSTATE_INITIALIZED: clear_script_queue(This); + release_persistent_script_objs(This);
if(This->ctx->host_global) { IDispatch_Release(This->ctx->host_global); @@ -423,6 +460,7 @@ static void decrease_state(JScript *This, SCRIPTSTATE state)
if(iter->disp) IDispatch_Release(iter->disp); + release_named_item_script_obj(iter); release_named_item(iter); iter = iter2; } @@ -843,6 +881,7 @@ static HRESULT WINAPI JScript_AddNamedItem(IActiveScript *iface, item->ref = 1; item->disp = disp; item->flags = dwFlags; + item->script_obj = NULL; item->name = heap_strdupW(pstrName); if(!item->name) { if(disp) @@ -869,6 +908,7 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR IDispatch **ppdisp) { JScript *This = impl_from_IActiveScript(iface); + jsdisp_t *script_obj;
TRACE("(%p)->(%s %p)\n", This, debugstr_w(pstrItemName), ppdisp);
@@ -880,7 +920,14 @@ static HRESULT WINAPI JScript_GetScriptDispatch(IActiveScript *iface, LPCOLESTR return E_UNEXPECTED; }
- *ppdisp = to_disp(This->ctx->global); + script_obj = This->ctx->global; + if(pstrItemName) { + named_item_t *item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) return E_INVALIDARG; + if(item->script_obj) script_obj = item->script_obj; + } + + *ppdisp = to_disp(script_obj); IDispatch_AddRef(*ppdisp); return S_OK; } @@ -1001,6 +1048,7 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, DWORD dwFlags, VARIANT *pvarResult, EXCEPINFO *pexcepinfo) { JScript *This = impl_from_IActiveScriptParse(iface); + named_item_t *item = NULL; bytecode_t *code; jsexcept_t ei; HRESULT hres; @@ -1012,11 +1060,24 @@ static HRESULT WINAPI JScriptParse_ParseScriptText(IActiveScriptParse *iface, if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED;
+ if(pstrItemName) { + item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) { + WARN("Unknown context %s\n", debugstr_w(pstrItemName)); + return E_INVALIDARG; + } + if(!item->script_obj) item = NULL; + } + enter_script(This->ctx, &ei); hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLine, NULL, pstrDelimiter, (dwFlags & SCRIPTTEXT_ISEXPRESSION) != 0, This->is_encode, &code); if(FAILED(hres)) return leave_script(This->ctx, hres); + if(item) { + code->named_item = item; + item->ref++; + }
if(dwFlags & SCRIPTTEXT_ISEXPRESSION) { jsval_t r; @@ -1093,6 +1154,7 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars CTXARG_T dwSourceContextCookie, ULONG ulStartingLineNumber, DWORD dwFlags, IDispatch **ppdisp) { JScript *This = impl_from_IActiveScriptParseProcedure2(iface); + named_item_t *item = NULL; bytecode_t *code; jsdisp_t *dispex; jsexcept_t ei; @@ -1105,11 +1167,25 @@ static HRESULT WINAPI JScriptParseProcedure_ParseProcedureText(IActiveScriptPars if(This->thread_id != GetCurrentThreadId() || This->ctx->state == SCRIPTSTATE_CLOSED) return E_UNEXPECTED;
+ if(pstrItemName) { + item = lookup_named_item(This->ctx, pstrItemName, 0); + if(!item) { + WARN("Unknown context %s\n", debugstr_w(pstrItemName)); + return E_INVALIDARG; + } + if(!item->script_obj) item = NULL; + } + enter_script(This->ctx, &ei); hres = compile_script(This->ctx, pstrCode, dwSourceContextCookie, ulStartingLineNumber, pstrFormalParams, pstrDelimiter, FALSE, This->is_encode, &code); - if(SUCCEEDED(hres)) + if(SUCCEEDED(hres)) { + if(item) { + code->named_item = item; + item->ref++; + } hres = create_source_function(This->ctx, code, &code->global_code, NULL, &dispex); + } release_bytecode(code); hres = leave_script(This->ctx, hres); if(FAILED(hres)) diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index efd5a54..bf7a179 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -205,6 +205,7 @@ typedef HRESULT (*builtin_setter_t)(script_ctx_t*,jsdisp_t*,jsval_t); HRESULT builtin_set_const(script_ctx_t*,jsdisp_t*,jsval_t) DECLSPEC_HIDDEN;
typedef struct named_item_t { + jsdisp_t *script_obj; IDispatch *disp; unsigned ref; DWORD flags; @@ -213,6 +214,7 @@ typedef struct named_item_t { struct named_item_t *next; } named_item_t;
+HRESULT create_named_item_script_obj(script_ctx_t*,named_item_t*) DECLSPEC_HIDDEN; named_item_t *lookup_named_item(script_ctx_t*,const WCHAR*,unsigned) DECLSPEC_HIDDEN; void release_named_item(named_item_t*) DECLSPEC_HIDDEN;