Jacek Caban : jscript: Added Object.getOwnPropertyDescriptor implementation.
Alexandre Julliard
julliard at winehq.org
Thu May 10 18:23:16 CDT 2018
Module: wine
Branch: master
Commit: 551e5a77e24d7b93808b127d16a97d65288e2864
URL: https://source.winehq.org/git/wine.git/?a=commit;h=551e5a77e24d7b93808b127d16a97d65288e2864
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu May 10 19:19:56 2018 +0200
jscript: Added Object.getOwnPropertyDescriptor implementation.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/jscript/dispex.c | 32 +++++++++++++++
dlls/jscript/jscript.h | 7 ++++
dlls/jscript/object.c | 83 ++++++++++++++++++++++++++++++++++++++-
dlls/mshtml/tests/documentmode.js | 4 ++
dlls/mshtml/tests/es5.js | 43 +++++++++++++++++---
5 files changed, 163 insertions(+), 6 deletions(-)
diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c
index d3f345a..5ba5b70 100644
--- a/dlls/jscript/dispex.c
+++ b/dlls/jscript/dispex.c
@@ -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;
+}
diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h
index 9c28da0..ab7d634 100644
--- a/dlls/jscript/jscript.h
+++ b/dlls/jscript/jscript.h
@@ -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;
diff --git a/dlls/jscript/object.c b/dlls/jscript/object.c
index de09060..72365c7 100644
--- a/dlls/jscript/object.c
+++ b/dlls/jscript/object.c
@@ -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);
}
diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js
index 3fbb2fb..1525b09 100644
--- a/dlls/mshtml/tests/documentmode.js
+++ b/dlls/mshtml/tests/documentmode.js
@@ -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);
diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js
index d539557..efdfb0a 100644
--- a/dlls/mshtml/tests/es5.js
+++ b/dlls/mshtml/tests/es5.js
@@ -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
];
More information about the wine-cvs
mailing list