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