jscript: Added support for Function.arguments property.
This commit is contained in:
parent
76c06a6d94
commit
922efb88bb
|
@ -35,6 +35,7 @@ typedef struct {
|
|||
const WCHAR *src_str;
|
||||
DWORD src_len;
|
||||
DWORD length;
|
||||
DispatchEx *arguments;
|
||||
} FunctionInstance;
|
||||
|
||||
static inline FunctionInstance *function_from_vdisp(vdisp_t *vdisp)
|
||||
|
@ -53,6 +54,7 @@ static const WCHAR lengthW[] = {'l','e','n','g','t','h',0};
|
|||
static const WCHAR toStringW[] = {'t','o','S','t','r','i','n','g',0};
|
||||
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 IDispatch *get_this(DISPPARAMS *dp)
|
||||
{
|
||||
|
@ -157,29 +159,20 @@ static HRESULT create_arguments(script_ctx_t *ctx, IDispatch *calee, DISPPARAMS
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DISPPARAMS *dp, jsexcept_t *ei,
|
||||
IServiceProvider *caller, DispatchEx **ret)
|
||||
static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DispatchEx *arg_disp,
|
||||
DISPPARAMS *dp, jsexcept_t *ei, IServiceProvider *caller, DispatchEx **ret)
|
||||
{
|
||||
DispatchEx *var_disp, *arg_disp;
|
||||
DispatchEx *var_disp;
|
||||
VARIANT var;
|
||||
HRESULT hres;
|
||||
|
||||
static const WCHAR argumentsW[] = {'a','r','g','u','m','e','n','t','s',0};
|
||||
|
||||
hres = create_dispex(ctx, NULL, NULL, &var_disp);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex),
|
||||
dp, ei, caller, &arg_disp);
|
||||
if(SUCCEEDED(hres)) {
|
||||
VARIANT var;
|
||||
|
||||
V_VT(&var) = VT_DISPATCH;
|
||||
V_DISPATCH(&var) = (IDispatch*)_IDispatchEx_(arg_disp);
|
||||
hres = jsdisp_propput_name(var_disp, argumentsW, &var, ei, caller);
|
||||
jsdisp_release(arg_disp);
|
||||
}
|
||||
|
||||
if(SUCCEEDED(hres))
|
||||
hres = init_parameters(var_disp, function, dp, ei, caller);
|
||||
if(FAILED(hres)) {
|
||||
|
@ -194,7 +187,7 @@ static HRESULT create_var_disp(script_ctx_t *ctx, FunctionInstance *function, DI
|
|||
static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDispatch *this_obj, DISPPARAMS *dp,
|
||||
VARIANT *retv, jsexcept_t *ei, IServiceProvider *caller)
|
||||
{
|
||||
DispatchEx *var_disp;
|
||||
DispatchEx *var_disp, *arg_disp;
|
||||
exec_ctx_t *exec_ctx;
|
||||
scope_chain_t *scope;
|
||||
HRESULT hres;
|
||||
|
@ -204,21 +197,34 @@ static HRESULT invoke_source(script_ctx_t *ctx, FunctionInstance *function, IDis
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
hres = create_var_disp(ctx, function, dp, ei, caller, &var_disp);
|
||||
hres = create_arguments(ctx, (IDispatch*)_IDispatchEx_(&function->dispex),
|
||||
dp, ei, caller, &arg_disp);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = create_var_disp(ctx, function, arg_disp, dp, ei, caller, &var_disp);
|
||||
if(FAILED(hres)) {
|
||||
jsdisp_release(arg_disp);
|
||||
return hres;
|
||||
}
|
||||
|
||||
hres = scope_push(function->scope_chain, var_disp, &scope);
|
||||
if(SUCCEEDED(hres)) {
|
||||
hres = create_exec_ctx(ctx, this_obj, var_disp, scope, &exec_ctx);
|
||||
scope_release(scope);
|
||||
}
|
||||
jsdisp_release(var_disp);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
if(SUCCEEDED(hres)) {
|
||||
DispatchEx *prev_args;
|
||||
|
||||
prev_args = function->arguments;
|
||||
function->arguments = arg_disp;
|
||||
hres = exec_source(exec_ctx, function->parser, function->source, EXECT_FUNCTION, ei, retv);
|
||||
function->arguments = prev_args;
|
||||
|
||||
jsdisp_release(arg_disp);
|
||||
exec_release(exec_ctx);
|
||||
}
|
||||
|
||||
return hres;
|
||||
}
|
||||
|
@ -531,6 +537,35 @@ HRESULT Function_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, DISPPARAM
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Function_arguments(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
|
||||
DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp)
|
||||
{
|
||||
FunctionInstance *function = (FunctionInstance*)jsthis->u.jsdisp;
|
||||
HRESULT hres = S_OK;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
switch(flags) {
|
||||
case DISPATCH_PROPERTYGET: {
|
||||
if(function->arguments) {
|
||||
IDispatchEx_AddRef(_IDispatchEx_(function->arguments));
|
||||
V_VT(retv) = VT_DISPATCH;
|
||||
V_DISPATCH(retv) = (IDispatch*)_IDispatchEx_(function->arguments);
|
||||
}else {
|
||||
V_VT(retv) = VT_NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DISPATCH_PROPERTYPUT:
|
||||
break;
|
||||
default:
|
||||
FIXME("unimplemented flags %x\n", flags);
|
||||
hres = E_NOTIMPL;
|
||||
}
|
||||
|
||||
return hres;
|
||||
}
|
||||
|
||||
static void Function_destructor(DispatchEx *dispex)
|
||||
{
|
||||
FunctionInstance *This = (FunctionInstance*)dispex;
|
||||
|
@ -544,6 +579,7 @@ static void Function_destructor(DispatchEx *dispex)
|
|||
|
||||
static const builtin_prop_t Function_props[] = {
|
||||
{applyW, Function_apply, PROPF_METHOD|2},
|
||||
{argumentsW, Function_arguments, 0},
|
||||
{callW, Function_call, PROPF_METHOD|1},
|
||||
{lengthW, Function_length, 0},
|
||||
{toStringW, Function_toString, PROPF_METHOD}
|
||||
|
|
|
@ -69,11 +69,13 @@ function testFunc1(x, y) {
|
|||
ok(arguments["0"] === true, "arguments[0] is not true");
|
||||
ok(arguments["1"] === "test", "arguments[1] is not \"test\"");
|
||||
ok(arguments.callee === testFunc1, "arguments.calee !== testFunc1");
|
||||
ok(testFunc1.arguments === arguments, "testFunc1.arguments = " + testFunc1.arguments);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ok(testFunc1.length === 2, "testFunc1.length is not 2");
|
||||
ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments);
|
||||
|
||||
ok(Object.prototype !== undefined, "Object.prototype is undefined");
|
||||
ok(Object.prototype.prototype === undefined, "Object.prototype is not undefined");
|
||||
|
@ -109,6 +111,22 @@ ok(typeof(this) === "object", "typeof(this) is not object");
|
|||
|
||||
ok(testFunc1(true, "test") === true, "testFunc1 not returned true");
|
||||
|
||||
ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments);
|
||||
|
||||
function testRecFunc(x) {
|
||||
ok(testRecFunc.arguments === arguments, "testRecFunc.arguments = " + testRecFunc.arguments);
|
||||
if(x) {
|
||||
testRecFunc(false);
|
||||
ok(testRecFunc.arguments === arguments, "testRecFunc.arguments = " + testRecFunc.arguments);
|
||||
ok(testRecFunc.arguments[0] === true, "testRecFunc.arguments.x = " + testRecFunc.arguments[0]);
|
||||
}
|
||||
}
|
||||
|
||||
testRecFunc.arguments = 5;
|
||||
ok(testRecFunc.arguments === null, "testRecFunc.arguments = " + testRecFunc.arguments);
|
||||
testRecFunc(true);
|
||||
ok(testRecFunc.arguments === null, "testRecFunc.arguments = " + testRecFunc.arguments);
|
||||
|
||||
tmp = (function() {1;})();
|
||||
ok(tmp === undefined, "tmp = " + tmp);
|
||||
tmp = eval("1;");
|
||||
|
|
Loading…
Reference in New Issue