mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 12:54:13 +00:00
jscript: Implement caller
for function instances and prototype.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com>
This commit is contained in:
parent
e748ead5cf
commit
426f4bb3ea
4 changed files with 82 additions and 1 deletions
|
@ -270,6 +270,26 @@ HRESULT Function_invoke(jsdisp_t *func_this, jsval_t vthis, WORD flags, unsigned
|
|||
return function->vtbl->call(function->dispex.ctx, function, vthis, flags, argc, argv, r);
|
||||
}
|
||||
|
||||
static HRESULT Function_get_caller(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
|
||||
{
|
||||
FunctionInstance *function = function_from_jsdisp(jsthis);
|
||||
call_frame_t *frame;
|
||||
|
||||
TRACE("%p\n", jsthis);
|
||||
|
||||
for(frame = ctx->call_ctx; frame; frame = frame->prev_frame) {
|
||||
if(frame->function_instance == &function->dispex) {
|
||||
if(!frame->prev_frame || !frame->prev_frame->function_instance)
|
||||
break;
|
||||
*r = jsval_obj(jsdisp_addref(frame->prev_frame->function_instance));
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
*r = jsval_null();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT Function_get_length(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
|
||||
{
|
||||
TRACE("%p\n", jsthis);
|
||||
|
@ -565,6 +585,7 @@ static const builtin_prop_t Function_props[] = {
|
|||
{L"arguments", NULL, 0, Function_get_arguments},
|
||||
{L"bind", Function_bind, PROPF_METHOD|PROPF_ES5|1},
|
||||
{L"call", Function_call, PROPF_METHOD|1},
|
||||
{L"caller", NULL, PROPF_HTML, Function_get_caller},
|
||||
{L"length", NULL, 0, Function_get_length},
|
||||
{L"toString", Function_toString, PROPF_METHOD}
|
||||
};
|
||||
|
@ -584,6 +605,7 @@ static const builtin_info_t Function_info = {
|
|||
|
||||
static const builtin_prop_t FunctionInst_props[] = {
|
||||
{L"arguments", NULL, 0, Function_get_arguments},
|
||||
{L"caller", NULL, PROPF_HTML, Function_get_caller},
|
||||
{L"length", NULL, 0, Function_get_length}
|
||||
};
|
||||
|
||||
|
@ -769,6 +791,7 @@ static HRESULT InterpretedFunction_set_prototype(script_ctx_t *ctx, jsdisp_t *js
|
|||
|
||||
static const builtin_prop_t InterpretedFunction_props[] = {
|
||||
{L"arguments", NULL, 0, Function_get_arguments},
|
||||
{L"caller", NULL, PROPF_HTML, Function_get_caller},
|
||||
{L"length", NULL, 0, Function_get_length},
|
||||
{L"prototype", NULL, 0, InterpretedFunction_get_prototype, InterpretedFunction_set_prototype}
|
||||
};
|
||||
|
@ -889,6 +912,30 @@ HRESULT create_source_function(script_ctx_t *ctx, bytecode_t *code, function_cod
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT BindFunction_get_caller(script_ctx_t *ctx, jsdisp_t *jsthis, jsval_t *r)
|
||||
{
|
||||
return JS_E_INVALID_ACTION;
|
||||
}
|
||||
|
||||
static const builtin_prop_t BindFunction_props[] = {
|
||||
{L"arguments", NULL, 0, Function_get_arguments},
|
||||
{L"caller", NULL, 0, BindFunction_get_caller},
|
||||
{L"length", NULL, 0, Function_get_length}
|
||||
};
|
||||
|
||||
static const builtin_info_t BindFunction_info = {
|
||||
JSCLASS_FUNCTION,
|
||||
Function_value,
|
||||
ARRAY_SIZE(BindFunction_props),
|
||||
BindFunction_props,
|
||||
Function_destructor,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
Function_gc_traverse
|
||||
};
|
||||
|
||||
static HRESULT BindFunction_call(script_ctx_t *ctx, FunctionInstance *func, jsval_t vthis, unsigned flags,
|
||||
unsigned argc, jsval_t *argv, jsval_t *r)
|
||||
{
|
||||
|
@ -975,7 +1022,7 @@ static HRESULT create_bind_function(script_ctx_t *ctx, FunctionInstance *target,
|
|||
BindFunction *function;
|
||||
HRESULT hres;
|
||||
|
||||
hres = create_function(ctx, NULL, &BindFunctionVtbl, FIELD_OFFSET(BindFunction, args[argc]), PROPF_METHOD,
|
||||
hres = create_function(ctx, &BindFunction_info, &BindFunctionVtbl, FIELD_OFFSET(BindFunction, args[argc]), PROPF_METHOD,
|
||||
FALSE, NULL, (void**)&function);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
|
|
@ -286,6 +286,7 @@ ok(unescape(escape(tmp)) === tmp, "unescape(escape('" + tmp + "')) = " + unescap
|
|||
ok(Object.prototype.hasOwnProperty('toString'), "Object.prototype.hasOwnProperty('toString') is false");
|
||||
ok(Object.prototype.hasOwnProperty('isPrototypeOf'), "Object.prototype.hasOwnProperty('isPrototypeOf') is false");
|
||||
ok(Function.prototype.hasOwnProperty('call'), "Function.prototype.hasOwnProperty('call') is false");
|
||||
ok(!Function.prototype.hasOwnProperty('caller'), "Function.prototype.hasOwnProperty('caller') is true");
|
||||
|
||||
Object();
|
||||
new Object();
|
||||
|
|
|
@ -840,6 +840,27 @@ sync_test("for..in", function() {
|
|||
ok(found === 1, "ondragstart enumerated " + found + " times in document after set to empty string");
|
||||
});
|
||||
|
||||
sync_test("function caller", function() {
|
||||
ok(Function.prototype.hasOwnProperty("caller"), "caller not prop of Function.prototype");
|
||||
|
||||
function test_caller(expected_caller, stop) {
|
||||
ok(test_caller.caller === expected_caller, "caller = " + test_caller.caller);
|
||||
if(stop) return;
|
||||
function nested() {
|
||||
ok(nested.caller === test_caller, "nested caller = " + nested.caller);
|
||||
test_caller(nested, true);
|
||||
ok(test_caller.caller === expected_caller, "caller within nested = " + test_caller.caller);
|
||||
}
|
||||
nested();
|
||||
ok(test_caller.caller === expected_caller, "caller after nested = " + test_caller.caller);
|
||||
}
|
||||
ok(test_caller.hasOwnProperty("caller"), "caller not prop of test_caller");
|
||||
ok(test_caller.caller === null, "test_caller.caller = " + test_caller.caller);
|
||||
|
||||
function f1() { test_caller(f1); } f1();
|
||||
function f2() { test_caller(f2); } f2();
|
||||
});
|
||||
|
||||
sync_test("elem_by_id", function() {
|
||||
document.body.innerHTML = '<form id="testid" name="testname"></form>';
|
||||
var v = document.documentMode, found, i;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
var E_INVALIDARG = 0x80070057;
|
||||
var JS_E_PROP_DESC_MISMATCH = 0x800a01bd;
|
||||
var JS_E_INVALID_ACTION = 0x800a01bd;
|
||||
var JS_E_NUMBER_EXPECTED = 0x800a1389;
|
||||
var JS_E_FUNCTION_EXPECTED = 0x800a138a;
|
||||
var JS_E_DATE_EXPECTED = 0x800a138e;
|
||||
|
@ -525,11 +526,14 @@ sync_test("getOwnPropertyDescriptor", function() {
|
|||
(function() {
|
||||
test_own_data_prop_desc(arguments, "length", true, false, true);
|
||||
test_own_data_prop_desc(arguments, "callee", true, false, true);
|
||||
ok(!("caller" in arguments), "caller in arguments");
|
||||
})();
|
||||
|
||||
test_own_data_prop_desc(String, "prototype", false, false, false);
|
||||
test_own_data_prop_desc(function(){}, "prototype", true, false, false);
|
||||
test_own_data_prop_desc(function(){}, "caller", false, false, false);
|
||||
test_own_data_prop_desc(Function, "prototype", false, false, false);
|
||||
test_own_data_prop_desc(Function.prototype, "caller", false, false, false);
|
||||
test_own_data_prop_desc(String.prototype, "constructor", true, false, true);
|
||||
|
||||
try {
|
||||
|
@ -1136,6 +1140,14 @@ sync_test("bind", function() {
|
|||
r = f.call(o2);
|
||||
ok(r === 1, "r = " + r);
|
||||
|
||||
try {
|
||||
f.caller;
|
||||
ok(false, "expected exception getting f.caller");
|
||||
}catch(ex) {
|
||||
var n = ex.number >>> 0;
|
||||
ok(n === JS_E_INVALID_ACTION, "f.caller threw " + n);
|
||||
}
|
||||
|
||||
f = (function() {
|
||||
ok(this === o, "this != o");
|
||||
ok(arguments.length === 1, "arguments.length = " + arguments.length);
|
||||
|
|
Loading…
Reference in a new issue