jscript: Added Object.getOwnPropertyDescriptor implementation.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
54bcff15ef
commit
551e5a77e2
|
@ -1614,3 +1614,35 @@ HRESULT jsdisp_is_enumerable(jsdisp_t *obj, const WCHAR *name, BOOL *ret)
|
|||
*ret = prop && (prop->flags & PROPF_ENUMERABLE) && prop->type != PROP_PROTREF;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT jsdisp_get_own_property(jsdisp_t *obj, const WCHAR *name, BOOL flags_only,
|
||||
property_desc_t *desc)
|
||||
{
|
||||
dispex_prop_t *prop;
|
||||
HRESULT hres;
|
||||
|
||||
hres = find_prop_name(obj, string_hash(name), name, &prop);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(!prop)
|
||||
return DISP_E_UNKNOWNNAME;
|
||||
|
||||
memset(desc, 0, sizeof(*desc));
|
||||
|
||||
switch(prop->type) {
|
||||
case PROP_BUILTIN:
|
||||
case PROP_JSVAL:
|
||||
if(!flags_only) {
|
||||
hres = prop_get(obj, prop, &desc->value);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DISP_E_UNKNOWNNAME;
|
||||
}
|
||||
|
||||
desc->flags = prop->flags & (PROPF_ENUMERABLE | PROPF_WRITABLE | PROPF_CONFIGURABLE);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ typedef struct _jsval_t jsval_t;
|
|||
typedef struct _jsstr_t jsstr_t;
|
||||
typedef struct _script_ctx_t script_ctx_t;
|
||||
typedef struct _dispex_prop_t dispex_prop_t;
|
||||
typedef struct _property_desc_t property_desc_t;
|
||||
|
||||
typedef struct {
|
||||
void **blocks;
|
||||
|
@ -292,6 +293,7 @@ HRESULT jsdisp_get_id(jsdisp_t*,const WCHAR*,DWORD,DISPID*) DECLSPEC_HIDDEN;
|
|||
HRESULT disp_delete(IDispatch*,DISPID,BOOL*) DECLSPEC_HIDDEN;
|
||||
HRESULT disp_delete_name(script_ctx_t*,IDispatch*,jsstr_t*,BOOL*) DECLSPEC_HIDDEN;
|
||||
HRESULT jsdisp_delete_idx(jsdisp_t*,DWORD) DECLSPEC_HIDDEN;
|
||||
HRESULT jsdisp_get_own_property(jsdisp_t*,const WCHAR*,BOOL,property_desc_t*) DECLSPEC_HIDDEN;
|
||||
HRESULT jsdisp_is_own_prop(jsdisp_t*,const WCHAR*,BOOL*) DECLSPEC_HIDDEN;
|
||||
HRESULT jsdisp_is_enumerable(jsdisp_t*,const WCHAR*,BOOL*) DECLSPEC_HIDDEN;
|
||||
|
||||
|
@ -376,6 +378,11 @@ typedef struct {
|
|||
|
||||
#include "jsval.h"
|
||||
|
||||
struct _property_desc_t {
|
||||
unsigned flags;
|
||||
jsval_t value;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
EXCEPINFO ei;
|
||||
jsval_t val;
|
||||
|
|
|
@ -32,8 +32,16 @@ static const WCHAR propertyIsEnumerableW[] =
|
|||
{'p','r','o','p','e','r','t','y','I','s','E','n','u','m','e','r','a','b','l','e',0};
|
||||
static const WCHAR isPrototypeOfW[] = {'i','s','P','r','o','t','o','t','y','p','e','O','f',0};
|
||||
|
||||
static const WCHAR getOwnPropertyDescriptorW[] =
|
||||
{'g','e','t','O','w','n','P','r','o','p','e','r','t','y','D','e','s','c','r','i','p','t','o','r',0};
|
||||
|
||||
static const WCHAR default_valueW[] = {'[','o','b','j','e','c','t',' ','O','b','j','e','c','t',']',0};
|
||||
|
||||
static const WCHAR configurableW[] = {'c','o','n','f','i','g','u','r','a','b','l','e',0};
|
||||
static const WCHAR enumerableW[] = {'e','n','u','m','e','r','a','b','l','e',0};
|
||||
static const WCHAR valueW[] = {'v','a','l','u','e',0};
|
||||
static const WCHAR writableW[] = {'w','r','i','t','a','b','l','e',0};
|
||||
|
||||
static HRESULT Object_toString(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||
jsval_t *r)
|
||||
{
|
||||
|
@ -252,6 +260,79 @@ static const builtin_info_t ObjectInst_info = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void release_property_descriptor(property_desc_t *desc)
|
||||
{
|
||||
jsval_release(desc->value);
|
||||
}
|
||||
|
||||
static HRESULT Object_getOwnPropertyDescriptor(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags,
|
||||
unsigned argc, jsval_t *argv, jsval_t *r)
|
||||
{
|
||||
property_desc_t prop_desc;
|
||||
jsdisp_t *obj, *desc_obj;
|
||||
const WCHAR *name;
|
||||
jsstr_t *name_str;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
if(argc < 1 || !is_object_instance(argv[0]))
|
||||
return throw_type_error(ctx, JS_E_OBJECT_EXPECTED, NULL);
|
||||
obj = to_jsdisp(get_object(argv[0]));
|
||||
if(!obj) {
|
||||
FIXME("not implemented non-JS object\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
hres = to_flat_string(ctx, argc >= 2 ? argv[1] : jsval_undefined(), &name_str, &name);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = jsdisp_get_own_property(obj, name, FALSE, &prop_desc);
|
||||
jsstr_release(name_str);
|
||||
if(hres == DISP_E_UNKNOWNNAME) {
|
||||
if(r) *r = jsval_undefined();
|
||||
return S_OK;
|
||||
}
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = create_object(ctx, NULL, &desc_obj);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = jsdisp_propput_name(desc_obj, valueW, prop_desc.value);
|
||||
if(SUCCEEDED(hres))
|
||||
hres = jsdisp_propput_name(desc_obj, writableW,
|
||||
jsval_bool(!!(prop_desc.flags & PROPF_WRITABLE)));
|
||||
if(SUCCEEDED(hres))
|
||||
hres = jsdisp_propput_name(desc_obj, enumerableW,
|
||||
jsval_bool(!!(prop_desc.flags & PROPF_ENUMERABLE)));
|
||||
if(SUCCEEDED(hres))
|
||||
hres = jsdisp_propput_name(desc_obj, configurableW,
|
||||
jsval_bool(!!(prop_desc.flags & PROPF_CONFIGURABLE)));
|
||||
|
||||
release_property_descriptor(&prop_desc);
|
||||
if(SUCCEEDED(hres) && r)
|
||||
*r = jsval_obj(desc_obj);
|
||||
else
|
||||
jsdisp_release(desc_obj);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static const builtin_prop_t ObjectConstr_props[] = {
|
||||
{getOwnPropertyDescriptorW, Object_getOwnPropertyDescriptor, PROPF_ES5|PROPF_METHOD|2}
|
||||
};
|
||||
|
||||
static const builtin_info_t ObjectConstr_info = {
|
||||
JSCLASS_FUNCTION,
|
||||
DEFAULT_FUNCTION_VALUE,
|
||||
sizeof(ObjectConstr_props)/sizeof(*ObjectConstr_props),
|
||||
ObjectConstr_props,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
static HRESULT ObjectConstr_value(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsigned argc, jsval_t *argv,
|
||||
jsval_t *r)
|
||||
{
|
||||
|
@ -303,7 +384,7 @@ HRESULT create_object_constr(script_ctx_t *ctx, jsdisp_t *object_prototype, jsdi
|
|||
{
|
||||
static const WCHAR ObjectW[] = {'O','b','j','e','c','t',0};
|
||||
|
||||
return create_builtin_constructor(ctx, ObjectConstr_value, ObjectW, NULL, PROPF_CONSTR,
|
||||
return create_builtin_constructor(ctx, ObjectConstr_value, ObjectW, &ObjectConstr_info, PROPF_CONSTR,
|
||||
object_prototype, ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -140,6 +140,10 @@ function test_javascript() {
|
|||
test_exposed("toISOString", Date.prototype, v >= 9);
|
||||
test_exposed("isArray", Array, v >= 9);
|
||||
test_exposed("indexOf", Array.prototype, v >= 9);
|
||||
/* FIXME: IE8 implements weird semi-functional property descriptors. */
|
||||
if(v != 8) {
|
||||
test_exposed("getOwnPropertyDescriptor", Object, v >= 8);
|
||||
}
|
||||
|
||||
test_parses("if(false) { o.default; }", v >= 9);
|
||||
test_parses("if(false) { o.with; }", v >= 9);
|
||||
|
|
|
@ -28,8 +28,6 @@ function test_date_now() {
|
|||
}
|
||||
|
||||
function test_toISOString() {
|
||||
var s;
|
||||
|
||||
function expect(date, expected) {
|
||||
var s = date.toISOString();
|
||||
ok(s === expected, "toISOString returned " + s + " expected " + expected);
|
||||
|
@ -53,8 +51,6 @@ function test_toISOString() {
|
|||
expect(new Date(-6216721920000100), "-195031-12-03T23:59:59.900Z");
|
||||
expect(new Date(1092830912830100), "+036600-06-07T22:27:10.100Z");
|
||||
|
||||
trace("" + 0xdeadbeef);
|
||||
|
||||
expect_exception(function() { new Date(NaN).toISOString(); });
|
||||
expect_exception(function() { new Date(31494784780800001).toISOString(); });
|
||||
|
||||
|
@ -147,10 +143,47 @@ function test_identifier_keywords() {
|
|||
next_test();
|
||||
}
|
||||
|
||||
function test_own_data_prop_desc(obj, prop, expected_writable, expected_enumerable,
|
||||
expected_configurable) {
|
||||
var desc = Object.getOwnPropertyDescriptor(obj, prop);
|
||||
ok("value" in desc, "value is not in desc");
|
||||
ok(desc.value === obj[prop], "desc.value = " + desc.value + " expected " + obj[prop]);
|
||||
ok(desc.writable === expected_writable, "desc(" + prop + ").writable = " + desc.writable
|
||||
+ " expected " + expected_writable);
|
||||
ok(desc.enumerable === expected_enumerable, "desc.enumerable = " + desc.enumerable
|
||||
+ " expected " + expected_enumerable);
|
||||
ok(desc.configurable === expected_configurable, "desc.configurable = " + desc.configurable
|
||||
+ " expected " + expected_configurable);
|
||||
}
|
||||
|
||||
function test_getOwnPropertyDescriptor() {
|
||||
var obj;
|
||||
|
||||
obj = { test: 1 };
|
||||
test_own_data_prop_desc(obj, "test", true, true, true);
|
||||
|
||||
test_own_data_prop_desc(Object, "getOwnPropertyDescriptor", true, false, true);
|
||||
test_own_data_prop_desc(Math, "PI", false, false, false);
|
||||
|
||||
var obj = new String();
|
||||
ok(Object.getOwnPropertyDescriptor(obj, "slice") === undefined,
|
||||
"getOwnPropertyDescriptor(slice) did not return undefined");
|
||||
test_own_data_prop_desc(String.prototype, "slice", true, false, true);
|
||||
|
||||
obj = new Array();
|
||||
test_own_data_prop_desc(obj, "length", true, false, false);
|
||||
|
||||
obj = /test/;
|
||||
test_own_data_prop_desc(obj, "lastIndex", true, false, false);
|
||||
|
||||
next_test();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
test_date_now,
|
||||
test_toISOString,
|
||||
test_indexOf,
|
||||
test_isArray,
|
||||
test_identifier_keywords
|
||||
test_identifier_keywords,
|
||||
test_getOwnPropertyDescriptor
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue