heap_free(scope);
}
-HRESULT create_exec_ctx(IDispatch *this_obj, DispatchEx *var_disp, scope_chain_t *scope, exec_ctx_t **ret)
+HRESULT create_exec_ctx(script_ctx_t *script_ctx, IDispatch *this_obj, DispatchEx *var_disp,
+ scope_chain_t *scope, exec_ctx_t **ret)
{
exec_ctx_t *ctx;
ctx->ref = 1;
- IDispatch_AddRef(this_obj);
- ctx->this_obj = this_obj;
+ if(this_obj)
+ ctx->this_obj = this_obj;
+ else if(script_ctx->host_global)
+ ctx->this_obj = script_ctx->host_global;
+ else
+ ctx->this_obj = (IDispatch*)_IDispatchEx_(script_ctx->global);
+ IDispatch_AddRef(ctx->this_obj);
IDispatchEx_AddRef(_IDispatchEx_(var_disp));
ctx->var_disp = var_disp;
}
}
- hres = jsdisp_get_id(ctx->parser->script->script_disp, identifier, 0, &id);
- if(SUCCEEDED(hres)) {
- exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id);
- return S_OK;
- }
-
if(lookup_global_members(ctx->parser->script, identifier, ret))
return S_OK;
if(flags & EXPR_NEWREF) {
- hres = jsdisp_get_id(ctx->parser->script->script_disp, identifier, fdexNameEnsure, &id);
+ hres = jsdisp_get_id(ctx->parser->script->global, identifier, fdexNameEnsure, &id);
if(FAILED(hres))
return hres;
- exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->script_disp), id);
+ exprval_set_idref(ret, (IDispatch*)_IDispatchEx_(ctx->parser->script->global), id);
return S_OK;
}
}
void exec_release(exec_ctx_t*);
-HRESULT create_exec_ctx(IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**);
+HRESULT create_exec_ctx(script_ctx_t*,IDispatch*,DispatchEx*,scope_chain_t*,exec_ctx_t**);
HRESULT exec_source(exec_ctx_t*,parser_ctx_t*,source_elements_t*,jsexcept_t*,VARIANT*);
typedef struct _statement_t statement_t;
hres = scope_push(function->scope_chain, var_disp, &scope);
if(SUCCEEDED(hres)) {
- hres = create_exec_ctx(this_obj, var_disp, scope, &exec_ctx);
+ hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx);
scope_release(scope);
}
if(FAILED(hres))
return hres;
}
-static HRESULT invoke_function(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp,
- VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
-{
- IDispatch *this_obj;
-
- if(!(this_obj = get_this(dp)))
- this_obj = (IDispatch*)_IDispatchEx_(ctx->script_disp);
-
- return invoke_source(ctx, function, this_obj, dp, retv, ei, caller);
-}
-
static HRESULT invoke_constructor(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
return S_OK;
}
-static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, WORD flags, DISPPARAMS *dp,
+static HRESULT invoke_value_proc(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_disp, WORD flags, DISPPARAMS *dp,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
- IDispatch *this_disp;
vdisp_t vthis;
HRESULT hres;
- this_disp = get_this(dp);
if(this_disp)
set_disp(&vthis, this_disp);
+ else if(ctx->host_global)
+ set_disp(&vthis, ctx->host_global);
else
- set_jsdisp(&vthis, ctx->script_disp);
+ set_jsdisp(&vthis, ctx->global);
hres = function->value_proc(ctx, &vthis, flags, dp, retv, ei, caller);
static HRESULT call_function(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *args,
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
{
- HRESULT hres;
+ if(function->value_proc)
+ return invoke_value_proc(ctx, function, this_obj, DISPATCH_METHOD, args, retv, ei, caller);
- if(function->value_proc) {
- vdisp_t vthis;
-
- if(this_obj)
- set_disp(&vthis, this_obj);
- else
- set_jsdisp(&vthis, ctx->script_disp);
-
- hres = function->value_proc(ctx, &vthis, DISPATCH_METHOD, args, retv, ei, caller);
- vdisp_release(&vthis);
- }else {
- hres = invoke_source(ctx, function, this_obj ? this_obj : (IDispatch*)_IDispatchEx_(ctx->script_disp),
- args, retv, ei, caller);
- }
-
- return hres;
+ return invoke_source(ctx, function, this_obj, args, retv, ei, caller);
}
static HRESULT function_to_string(FunctionInstance *function, BSTR *ret)
switch(flags) {
case DISPATCH_METHOD:
if(function->value_proc)
- return invoke_value_proc(ctx, function, flags, dp, retv, ei, caller);
+ return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller);
- return invoke_function(ctx, function, dp, retv, ei, caller);
+ return invoke_source(ctx, function, get_this(dp), dp, retv, ei, caller);
case DISPATCH_PROPERTYGET: {
HRESULT hres;
case DISPATCH_CONSTRUCT:
if(function->value_proc)
- return invoke_value_proc(ctx, function, flags, dp, retv, ei, caller);
+ return invoke_value_proc(ctx, function, get_this(dp), flags, dp, retv, ei, caller);
return invoke_constructor(ctx, function, dp, retv, ei, caller);
VARIANT var;
HRESULT hres;
- hres = create_exec_ctx((IDispatch*)_IDispatchEx_(This->ctx->script_disp), This->ctx->script_disp, NULL, &exec_ctx);
+ hres = create_exec_ctx(This->ctx, NULL, This->ctx->global, NULL, &exec_ctx);
if(FAILED(hres))
return hres;
This->ctx->lcid = This->lcid;
- if(!This->ctx->script_disp) {
- hres = create_dispex(This->ctx, NULL, NULL, &This->ctx->script_disp);
- if(FAILED(hres))
- return hres;
- }
-
hres = init_global(This->ctx);
if(FAILED(hres))
return hres;
if(This->ctx->state == SCRIPTSTATE_DISCONNECTED)
change_state(This, SCRIPTSTATE_INITIALIZED);
+ if(This->ctx->host_global) {
+ IDispatch_Release(This->ctx->host_global);
+ This->ctx->host_global = NULL;
+ }
+
if(This->ctx->named_items) {
named_item_t *iter, *iter2;
if (This->site)
change_state(This, SCRIPTSTATE_CLOSED);
- if(This->ctx->script_disp) {
- jsdisp_release(This->ctx->script_disp);
- This->ctx->script_disp = NULL;
- }
-
if(This->ctx->global) {
jsdisp_release(This->ctx->global);
This->ctx->global = NULL;
WARN("object does not implement IDispatch\n");
return hres;
}
+
+ if(This->ctx->host_global)
+ IDispatch_Release(This->ctx->host_global);
+ IDispatch_AddRef(disp);
+ This->ctx->host_global = disp;
}
item = heap_alloc(sizeof(*item));
if(!ppdisp)
return E_POINTER;
- if(This->thread_id != GetCurrentThreadId() || !This->ctx->script_disp) {
+ if(This->thread_id != GetCurrentThreadId() || !This->ctx->global) {
*ppdisp = NULL;
return E_UNEXPECTED;
}
- *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->script_disp);
+ *ppdisp = (IDispatch*)_IDispatchEx_(This->ctx->global);
IDispatch_AddRef(*ppdisp);
return S_OK;
}
jsheap_t tmp_heap;
- DispatchEx *script_disp;
+ IDispatch *host_global;
+
DispatchEx *global;
DispatchEx *function_constr;
DispatchEx *array_constr;
DEFINE_EXPECT(OnEnterScript);
DEFINE_EXPECT(OnLeaveScript);
+static BSTR a2bstr(const char *str)
+{
+ BSTR ret;
+ int len;
+
+ len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ ret = SysAllocStringLen(NULL, len-1);
+ MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
+
+ return ret;
+}
+
#define test_state(s,ss) _test_state(__LINE__,s,ss)
static void _test_state(unsigned line, IActiveScript *script, SCRIPTSTATE exstate)
{
{
IDispatchEx *dispex;
IDispatch *disp;
+ BSTR str;
+ DISPID id;
HRESULT hres;
disp = (void*)0xdeadbeef;
IDispatch_Release(disp);
ok(hres == S_OK, "Could not get IDispatchEx interface: %08x\n", hres);
+ str = a2bstr("ActiveXObject");
+ hres = IDispatchEx_GetDispID(dispex, str, fdexNameCaseSensitive, &id);
+ SysFreeString(str);
+ ok(hres == S_OK, "GetDispID failed: %08x\n", hres);
+
IDispatchEx_Release(dispex);
}
#define DISPID_GLOBAL_TESTOBJ 0x1006
#define DISPID_GLOBAL_NULL_BSTR 0x1007
#define DISPID_GLOBAL_NULL_DISP 0x1008
+#define DISPID_GLOBAL_TESTTHIS 0x1009
+#define DISPID_GLOBAL_TESTTHIS2 0x100a
#define DISPID_TESTOBJ_PROP 0x2000
static BOOL strict_dispid_check;
static const char *test_name = "(null)";
+static IDispatch *script_disp;
static BSTR a2bstr(const char *str)
{
return DISP_E_UNKNOWNNAME;
}
+ if(!strcmp_wa(bstrName, "testThis")) {
+ ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
+ *pid = DISPID_GLOBAL_TESTTHIS;
+ return S_OK;
+ }
+
+ if(!strcmp_wa(bstrName, "testThis2")) {
+ ok(grfdex == fdexNameCaseSensitive, "grfdex = %x\n", grfdex);
+ *pid = DISPID_GLOBAL_TESTTHIS2;
+ return S_OK;
+ }
+
if(strict_dispid_check)
ok(0, "unexpected call %s\n", wine_dbgstr_w(bstrName));
return DISP_E_UNKNOWNNAME;
V_VT(pvarRes) = VT_DISPATCH;
V_DISPATCH(pvarRes) = NULL;
return S_OK;
+
+ case DISPID_GLOBAL_TESTTHIS:
+ ok(pdp != NULL, "pdp == NULL\n");
+ ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+ ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
+ ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+ ok(pvarRes == NULL, "pvarRes != NULL\n");
+ ok(pei != NULL, "pei == NULL\n");
+
+ ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(arg) = %d\n", V_VT(pdp->rgvarg));
+ ok(V_DISPATCH(pdp->rgvarg) == (IDispatch*)iface, "disp != iface\n");
+
+ return S_OK;
+
+ case DISPID_GLOBAL_TESTTHIS2:
+ ok(pdp != NULL, "pdp == NULL\n");
+ ok(pdp->rgvarg != NULL, "rgvarg == NULL\n");
+ ok(!pdp->rgdispidNamedArgs, "rgdispidNamedArgs != NULL\n");
+ ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
+ ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
+ ok(pvarRes == NULL, "pvarRes != NULL\n");
+ ok(pei != NULL, "pei == NULL\n");
+
+ ok(V_VT(pdp->rgvarg) == VT_DISPATCH, "V_VT(arg) = %d\n", V_VT(pdp->rgvarg));
+ ok(V_DISPATCH(pdp->rgvarg) != (IDispatch*)iface, "disp == iface\n");
+ ok(V_DISPATCH(pdp->rgvarg) == script_disp, "disp != script_disp\n");
+
+ return S_OK;
}
ok(0, "unexpected call %x\n", id);
return script;
}
-static void parse_script(BSTR script_str)
+static void parse_script(DWORD flags, BSTR script_str)
{
IActiveScriptParse *parser;
IActiveScript *engine;
ok(hres == S_OK, "SetScriptSite failed: %08x\n", hres);
hres = IActiveScript_AddNamedItem(engine, testW,
- SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|SCRIPTITEM_GLOBALMEMBERS);
+ SCRIPTITEM_ISVISIBLE|SCRIPTITEM_ISSOURCE|flags);
ok(hres == S_OK, "AddNamedItem failed: %08x\n", hres);
hres = IActiveScript_SetScriptState(engine, SCRIPTSTATE_STARTED);
ok(hres == S_OK, "SetScriptState(SCRIPTSTATE_STARTED) failed: %08x\n", hres);
+ hres = IActiveScript_GetScriptDispatch(engine, NULL, &script_disp);
+ ok(hres == S_OK, "GetScriptDispatch failed: %08x\n", hres);
+ ok(script_disp != NULL, "script_disp == NULL\n");
+ ok(script_disp != (IDispatch*)&Global, "script_disp == Global\n");
+
hres = IActiveScriptParse64_ParseScriptText(parser, script_str, NULL, NULL, NULL, 0, 0, 0, NULL, NULL);
ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
+ IDispatch_Release(script_disp);
IActiveScript_Release(engine);
IUnknown_Release(parser);
}
return hres;
}
-static void parse_script_a(const char *src)
+static void parse_script_af(DWORD flags, const char *src)
{
BSTR tmp = a2bstr(src);
- parse_script(tmp);
+ parse_script(flags, tmp);
SysFreeString(tmp);
}
+static void parse_script_a(const char *src)
+{
+ parse_script_af(SCRIPTITEM_GLOBALMEMBERS, src);
+}
+
static HRESULT parse_htmlscript_a(const char *src)
{
HRESULT hres;
strict_dispid_check = FALSE;
if(script_str)
- parse_script(script_str);
+ parse_script(SCRIPTITEM_GLOBALMEMBERS, script_str);
SysFreeString(script_str);
}
SET_EXPECT(global_success_d);
SET_EXPECT(global_success_i);
- parse_script(str);
+ parse_script(SCRIPTITEM_GLOBALMEMBERS, str);
CHECK_CALLED(global_success_d);
CHECK_CALLED(global_success_i);
parse_script_a("ok(String.prototype.concat.call(testObj, ' OK') === '1 OK', 'wrong concat result');");
CHECK_CALLED(testobj_value);
+ SET_EXPECT(global_propget_d);
+ SET_EXPECT(global_propget_i);
+ parse_script_a("this.testPropGet;");
+ CHECK_CALLED(global_propget_d);
+ CHECK_CALLED(global_propget_i);
+
+ SET_EXPECT(global_propget_d);
+ SET_EXPECT(global_propget_i);
+ parse_script_a("(function () { this.testPropGet; })();");
+ CHECK_CALLED(global_propget_d);
+ CHECK_CALLED(global_propget_i);
+
+ parse_script_a("testThis(this);");
+ parse_script_a("(function () { testThis(this); })();");
+
run_from_res("lang.js");
run_from_res("api.js");
run_from_res("regexp.js");
test_isvisible(FALSE);
test_isvisible(TRUE);
+ parse_script_af(0, "test.testThis2(this);");
+ parse_script_af(0, "(function () { test.testThis2(this); })();");
+
hres = parse_htmlscript_a("<!--");
ok(hres == S_OK, "ParseScriptText failed: %08x\n", hres);
hres = parse_htmlscript_a("-->");